Как в этом случае работает неявное приведение типов в SQL Server?
Когда я пытаюсь этот специальный запрос в SQL Server (предположим, UserId
поле NVARCHAR):
SELECT * FROM MyUser WHERE UserId = 123456
Я получаю эту ошибку:
Сообщение 245, Уровень 16, Состояние 1, Строка 1 Синтаксическая ошибка при преобразовании значения nvarchar 'foo' в столбец типа данных int.
Очевидно, что есть значение 'foo'
где-то внизу UserId
колонка.
Почему SQL Server пытается преобразовать весь мой столбец в INTEGER, а не делает то, что мне кажется очевидным: преобразование значения моего поиска в NVARCHAR?
3 ответа
Сравнение выполняется с использованием правил Приоритета типов данных:
Когда оператор объединяет два выражения разных типов данных, правила для приоритета типа данных указывают, что тип данных с более низким приоритетом преобразуется в тип данных с более высоким приоритетом.
NVARCHAR
тип (приоритет 25) преобразуется в int
(приоритет 16). Обратите внимание, что приоритет 1 означает "самый высокий".
Я думаю, что это потому, что он не может сравнивать два значения разных типов. Затем is должен преобразовать оба элемента сравнения равенства в один и тот же тип. Вот, int
предпочтительнее, я думаю.
Я верю int
имеет приоритет над nvarchar
тип, поэтому он должен неявно пытаться преобразовать nvarchar
к значению int.
РЕДАКТИРОВАТЬ # 1
"Но не будет ли разумно попытаться преобразовать значение, которое я дал, в тип поля, в котором я ищу, а не наоборот?"
Да, это было бы хорошо, если бы это было. Но я полагаю, это потому, что было бы слишком много попыток конверсии, которые можно было бы подразумевать при попытке какого-либо другого вида сравнения.
where dateOfBirth = 1976-6-16
против
where dateOfBirth = N'1976-06-16'
В первом примере, каково намерение пользователя? Это проверить dateOfBirth
равно значению даты 1976-06-16
или сравнить с целочисленным значением 1976 - 6 - 16
, что приведет к 1954
что может быть достаточно разумным, чтобы считать его годом любой данной даты.
Я думаю, что есть неявные преобразования, такие nvarchar
в datetime
, но было бы много, чтобы покрыть, поэтому они ограничились наиболее распространенным возможным преобразованием.
Почему вы указываете целочисленное значение, если знаете, что столбец - это NVARCHAR?
К сожалению, SQL Server, как и многие другие реализации SQL, сильно отстает от других языков в поддержке типов. Проверка типа обычно выполняется только во время выполнения. Таким образом, такие запросы, как ваш, не проверяются синтаксисом, чтобы выделить проблемы, подобные той, которая у вас есть. Ваш запрос ошибочен, потому что вы не соответствуете различным типам, но поскольку SQL Server не проверяет его, результаты будут непредсказуемыми, в зависимости от данных.