Конкатенация TSQL - PullRequest
       5

Конкатенация TSQL

5 голосов
/ 24 августа 2011

Мне часто нужно объединять поля в TSQL ...

При использовании оператора '+' 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 (IMO) мешает. По сути, он предпочитает математические функции над строковыми функциями. Желаю :-), чтобы DTP даже не рассматривался в данном случае - почему бы не настроить оператор '+' так, чтобы операция могла благоприятствовать success по сравнению с конкретными типы данных? Я не возражаю, если он по-прежнему предпочитает MATH, а не функции String, когда это возможно, но почему он не поддерживает функции String по сравнению с ошибками? (Единственный способ добиться успеха в 1) - это трактовать ее как строковую функцию, поэтому нет никакой двусмысленности.) Кто-то в Microsoft считал, что выдача ошибки в 1) будет более ценной для программиста, чем лечение «+» как строковая функция. Зачем? И почему они не предоставили способ переопределить это? (Или они ... это действительно суть моего вопроса.) SET STRING_PREFERENCE ON было бы неплохо! : -Р

Чтобы справиться с этим, вам нужно проделать больше работы - вам нужно явно преобразовать 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) способы, позволяющие избежать явных преобразований типов данных и нулевых проверок в каждом поле, где я должен убедиться, что оператор «+» ведет себя так, как мне нужно.

Спасибо!

EDIT
@ a1ex07 придумал отличный ответ для работы с проблемой NULL (SET CONCAT_NULL_YEILDS_NULL OFF), но, как я уже рассмотрел, кажется, что проблема заключается в том, чтобы заставить хранимые процедуры перекомпилироваться каждый раз, когда они выполняются.

Ответы [ 4 ]

8 голосов
/ 25 августа 2011

SQL Server 2012 имеет функцию CONCAT, которая решает все возникающие проблемы.

Хорошая сводка по функциональности предоставляется здесь SQL Menace

CONCAT принимает переменное число строковых аргументов и объединяет их в одну строку. Требуется минимум два входных значения; в противном случае возникает ошибка. Все аргументы неявно преобразуются на строковые типы, а затем объединены. Нулевые значения неявно преобразован в пустую строку. Если все аргументы равны нулю, тогда пустая строка типа varchar (1) возвращается. Неявное преобразование к строкам следует существующим правилам преобразования типов данных

2 голосов
/ 24 августа 2011

ОБНОВЛЕНИЕ
Вы можете использовать CONCAT_NULL_YIELDS_NULL , чтобы указать, NULL + 'txt' результаты NULL.Microsft говорит, что CONCAT_NULL_YIELDS_NULL не будет работать в следующих версиях SQL Server, но есть возможность установить его с помощью процедуры sp_dboption .Но, вероятно, лучше использовать ISNULL, как вы упомянули в вопросе.

1 голос
/ 25 июля 2012

Попробуйте это:

/*  1 */ SELECT cast(1 as varchar) + 'B'; /* = 1B */
/* or */ SELECT convert(varchar, 1) + 'B'; /* = 1B */

/*  2 */ SELECT cast(1 as varchar) + '1'; /* = 11 */

/*  3 */ SELECT '1' + '1'; /* = 11 */
/* or */ SELECT CONVERT(VARCHAR, '1') + CONVERT(VARCHAR, '1');

--NULL value:
DECLARE @A AS VARCHAR(10);
SET @A = NULL;
SELECT ISNULL(@A, '') + 1; /* = 1 */
0 голосов
/ 25 августа 2011

Нет ответа на этот вопрос для 2005 или 2008. Конкатенация без явных преобразований и нулевых проверок просто невозможна.

Похоже, что следующая версия SQL-Server будет иметь функцию CONCAT (спасибо@Martin), который звучит как точно , что я ищу.Недостатком является то, что, вероятно, пройдет не менее нескольких лет, прежде чем мое учреждение решит перейти на эту версию, так как они довольно стеснительны в том, чтобы быть ранними последователями, особенно когда речь идет о Microsoft.

Тамэто ярлык для NULL-проверок прямо сейчас (CONCAT_NULL_YIELDS_NULL - спасибо @ a1ex07), однако, использование этого имеет довольно большой штраф (перекомпилирует процедуру каждый раз, когда она выполняется), не говоря уже о том, что Microsoft не планирует поддерживатьэто в будущих версиях SQL-Server.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...