2010-11-19 5 views
1

Когда я пытаюсь это одноранговой запрос в SQL Server (предположим, что UserId является полем NVARCHAR):Каким образом работает листинг типа SQL Server в этом случае?

SELECT * FROM MyUser WHERE UserId = 123456 

Я получаю эту ошибку:

 
Msg 245, Level 16, State 1, Line 1 
Syntax error converting the nvarchar value 'foo' to a column of data type int. 

Очевидно, что это значение 'foo' где-то мой UserId колонка.

Почему SQL Server пытается преобразовать весь мой столбец в INTEGER вместо того, чтобы делать то, что кажется мне очевидным: преобразование значения моего поиска в NVARCHAR?

+0

Я не знаю, почему он это делает.Но это то, что он всегда делает :) –

ответ

3

Сравнение производится с использованием правил Data Type Precedence:

When an operator combines two expressions of different data types, the rules for data type precedence specify that the data type with the lower precedence is converted to the data type with the higher precedence.

NVARCHAR типа (25 старшинства) преобразуется в int (приоритет 16). Обратите внимание, что приоритет 1 означает «самый высокий».

+0

+1 Это именно то, что я пытался объяснить, как-то, своими словами. Спасибо за эту замечательную ссылку! =) –

+0

Я думаю, что это то, что оптимизатор запросов должен иметь возможность обрабатывать, прежде чем он передаст запрос в движок. Преобразуйте значение моего поиска в тип, который будет работать, выдаст предупреждение об этом и позвольте мне уйти от него. Ах хорошо. :-) – Tomalak

+0

@Tomalak: Может быть, в будущем выпуске SQL Server! = P Hehehe ... –

2

Я думаю, это потому, что он не может сравнивать два значения разных типов. Затем необходимо преобразовать элементы сравнения равенства в один и тот же тип. Здесь предпочтительнее int.

Я считаю, int имеет приоритет над nvarchar типа, поэтому он должен неявно попытаться преобразовать nvarchar в значение INT.

EDIT # 1

"But wouldn't it be sensible to try and convert the value I have given to the type of the field I am searching in, instead of the other way around?"

Да, это было бы хорошо, если бы это сделал. Но я предполагаю, что это связано с тем, что слишком много попыток конверсии подразумевают при попытке какого-то другого сравнения.

where dateOfBirth = 1976-6-16 

против

where dateOfBirth = N'1976-06-16' 

В первом примере, что такое намерение пользователя? Следует ли проверять, соответствует ли значение dateOfBirth значению даты 1976-06-16, или сравнить его с целым значением 1976 - 6 - 16, что приведет к 1954, что может быть достаточно разумным, чтобы рассматривать его как год любой даты.

Я думаю, что есть неявные преобразования, такие как nvarchar - datetime, но было бы много, чтобы покрыть, поэтому они ограничились самым распространенным возможным преобразованием.

+0

Но разве было бы разумно попытаться преобразовать значение, которое я дал типу поля, в котором я ищу, вместо того, чтобы наоборот? – Tomalak

+1

Да. Это раздражает, потому что, как представляется, умышленно избегать использования индекса, делая это, даже если у вас есть первичный ключ в UserID и искать тот, который находится в таблице, вы все равно можете найти результат, но вы также попадете в (т. е. вы получите возвращаемую строку результата _as well_ как ошибку из другой строки, которая не соответствует.) Oracle тоже делает это, и я никогда не видел в этом большого смысла; Я предполагаю, что это просто побочный эффект правил по умолчанию для продвижения/преобразования по умолчанию. –

+0

Намерение 'where dateOfBirth = 1976-6-16' явно является арифметическим результатом' 1976 - 6 - 16'. DATETIME - это числовой тип, пользователь дал числовой ввод (выражение, но тем не менее). Если я дам ему строку ('N'1976-06-16''), сервер * очевидно * преобразует его в DATETIME перед его использованием, иначе эти запросы не будут работать. Таким образом, на самом деле это могло бы быть достаточно умным, чтобы сделать то же самое в ситуации, описанной в моем вопросе. ;-) Но я действительно ценю, что так оно и есть. – Tomalak

1

Почему вы указываете целочисленное значение, если знаете столбец NVARCHAR?

К сожалению, SQL Server, как и многие реализации SQL, значительно отстает от других языков в поддержке типов. Проверка типов обычно выполняется только во время выполнения. Поэтому запросы, подобные вашим, не проверяются синтаксисом, чтобы выделять проблемы, подобные тем, которые у вас есть. Ваш запрос виноват, потому что вы несовпадаете с разными типами, но поскольку SQL Server не делает этого, результаты будут непредсказуемыми, в зависимости от данных.

+0

Почему? Потому что это был специальный запрос, и на этот раз я не думал вводить кавычки. Я был просто удивлен огромной глупостью сообщения об ошибке и задавался вопросом, было ли за этим более глубокое обоснование. Оказывается, нет - это «просто так». – Tomalak

+0

@Tomalak: гораздо лучшим сообщением об ошибке будет «несоответствие типа» - но разрешение все равно будет таким: исправьте свой запрос, чтобы указать правильный тип значения. – sqlvogel

+0

Я не хотел сказать, что * формулировка сообщения * была глупой, я говорю, как SQL Server * справляется с ситуацией * - это глупо. ;-) – Tomalak