TSQL заставляет вас иметь дело с двумя проблемами при использовании оператора '+': Приоритет типов данных и значения NULL.
При приоритете типов данных проблема заключается в ошибках преобразования.
1) SELECT 1 + 'B' = Conversion ERROR
2) SELECT 1 + '1' = 2
3) SELECT '1' + '1' = '11'
В 2) varchar '1' неявно преобразуется в int, и математика работает. Однако в 1) int 1 неявно преобразовывается в varchar. Вот где DTP (ИМО) мешает. По сути, он предпочитает математические функции строковым функциям. Я желаю :-), чтобы DTP даже не рассматривался в этом случае - почему бы не настроить оператор '+' так, чтобы операция могла способствовать успеху определенному типы данных? Я бы не возражал, если бы он по-прежнему отдавал предпочтение функциям MATH, а не строковым функциям, когда это возможно, но почему он не предпочитает строковые функции ошибкам? (Единственный способ добиться успеха в 1) - рассматривать ее как строковую функцию - так что здесь нет никакой двусмысленности.) Кто-то в Microsoft подумал, что выброс ошибки в 1) будет более ценным для программиста, чем лечение '+' как строковая функция. Зачем? И почему они не предоставили способ преодолеть это? (Или они ... это действительно суть моего вопроса.) SET STRING_PREFERENCE ON
было бы неплохо! :-P
Чтобы справиться с этим, вам нужно проделать больше работы - вы должны явно преобразовать 1 в varchar, используя любое количество различных строковых функций - обычно CAST / CONVERT, но также и многие другие (как LTRIM ()) будет работать.
Преобразования становятся трудоемкими, когда вы имеете дело с полями таблицы, когда вы не знаете тип данных. Это может сработать:
SELECT 'Fall ' + ' (' + [Term] + ')' -- Output: Fall (2011)
Но опять же, может и нет. Это просто зависит от типа данных [Term]. И что еще больше усложняет ситуацию, dba может изменить тип данных в какой-то момент, никому не сообщая (потому что это было частью большого пакета обновления, когда поставщик наконец понял, что в поле [Term] хранятся только числа, или по любой другой причине ).
Итак, если вы хотите быть мальчишкой, сделайте следующее:
SELECT 'Fall ' + ' (' + LTRIM([Term]) + ')'
Итак, теперь я запускаю эту функцию LTRIM каждый раз, хотя она может не понадобиться, потому что я не не знаю тип данных [Term] (хорошо - я могу это посмотреть, но это почти похоже на работу, и я не люблю прерывания, пока я кодирую :-P * grump ), а также я не знаю, что тип данных никогда не изменится.
Вторая проблема, с которой вы должны столкнуться при объединении TSQL, - это как работать со значениями NULL. Например, это не сработает:
SELECT NULL + 'B'
Итак, вам нужно сделать это:
SELECT 'Fall ' + ' (' + LTRIM(ISNULL([Term],'')) + ')'
Какая боль - я бы хотел просто сделать это:
SELECT 'Fall ' + ' (' + [Term] + ')'
Поэтому мне интересно, есть ли какие-либо (TSQL) способы избегать явных преобразований типов данных и проверок на null для каждого поля, где я должен убедиться, что оператор '+' ведет себя так, как мне нужно.
Спасибо!
EDIT
@ a1ex07 придумал отличный ответ для решения проблемы NULL ( SET CONCAT_NULL_YEILDS_NULL OFF
), но, когда я изучил его, он оказался проблематичным в плане принудительной повторной компиляции хранимых процедур при каждом их выполнении.