TSQL级联 我经常需要连接TSQL中的字段。。。

TSQL级联 我经常需要连接TSQL中的字段。。。,tsql,concatenation,Tsql,Concatenation,在使用“+”运算符时,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(国际海事组织)阻碍的地方。本质上,它更喜欢数学函数而不是字符串函数。我希望:-)

在使用“+”运算符时,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甚至都不是一个考虑因素——为什么不配置“+”操作符,以便操作能够比特定的数据类型更成功?如果可能的话,我不介意它还是喜欢数学而不是字符串函数——但为什么它不喜欢字符串函数而不是错误呢?(在1中取得成功的唯一方法是将其视为字符串函数——因此这里没有任何歧义。)微软有人认为在1)中抛出一个错误比将“+”视为字符串函数对程序员更有价值。为什么?为什么他们不提供一种方法来覆盖它?(或者他们……这真的是我问题的核心。)
设置字符串\u首选项就好了-P

为了解决这个问题,您必须做更多的工作——必须使用任意数量的不同字符串函数显式地将1转换为varchar——通常是CAST/convert,但其他许多函数(如LTRIM())也可以工作

在不知道数据类型的情况下处理表字段时,转换会变得非常耗时。这可能会奏效:

SELECT 'Fall '  + ' (' + [Term] + ')' -- Output: Fall (2011)
但话说回来,可能不会。这取决于[Term]的数据类型。更复杂的是,dba可能会在某个时候更改数据类型,而不告诉任何人(因为一旦供应商最终意识到[Term]字段中只存储了数字,或者出于任何原因,这是一个大型升级包的一部分)

因此,如果你想成为一名男童子军,你可以这样做:

SELECT 'Fall '  + ' (' + LTRIM([Term]) + ')'
所以现在我每次都在运行这个LTRIM函数,尽管它可能不是必需的,因为我不知道[Term]的数据类型(好的——我可以查一下,但这几乎就像工作一样,我不喜欢在编码时被中断:-p*grump),而且,我不知道数据类型永远不会改变

TSQL连接必须面对的第二个问题是如何处理空值。例如,这将失败:

SELECT NULL + 'B'
因此,您需要这样做:

SELECT 'Fall '  + ' (' + LTRIM(ISNULL([Term],'')) + ')'
多痛苦啊——我希望我能这么做:

SELECT 'Fall '  + ' (' + [Term] + ')'
因此,我想知道是否有任何(TSQL)方法可以避免对每个字段执行显式数据类型转换和空检查,在这些字段中,我必须确保“+”运算符按我需要的方式运行

谢谢

编辑

@a1ex07提出了一个很好的解决空问题的答案(
SET CONCAT\u NULL\u YEILDS\u NULL OFF
),但在我看来,强制存储过程在每次执行时重新编译似乎是有问题的。

更新
您可以使用指定是否为
NULL+'txt'
results
NULL

Microsoft表示,
CONCAT_NULL_-NULL
在SQL Server的进一步版本中不起作用,但仍有一个选项可以通过该过程进行设置。但是,正如您在问题中提到的,最好使用
ISNULL

对于2005年或2008年,没有答案。没有显式转换和空检查的串联是不可能的

看起来SQL Server的下一个版本将有一个CONCAT函数(谢谢@Martin),这听起来正是我想要的。不过,不利的一面是,我所在的机构决定升级到该版本可能至少需要几年时间,因为他们对于成为早期采用者非常害羞,尤其是在微软方面


现在有一个空检查的快捷方式(CONCAT_NULL_产生_NULL——感谢@a1ex07),但是,使用它会有相当大的代价(每次执行时都会重新编译过程),更不用说Microsoft不打算在SQL Server的未来版本中支持它。

SQL Server 2012确实具有解决您提出的所有问题的功能

下面是对该功能的一个很好的总结:

CONCAT接受数量可变的字符串参数并连接 把它们串成一根线。它至少需要两个输入值; 否则,将引发错误。所有参数都隐式转换 转换为字符串类型,然后连接。空值是隐式的 已转换为空字符串。如果所有参数都为null,则 返回varchar(1)类型的空字符串。隐式转换 to字符串遵循现有的数据类型转换规则

试试这个:


这叫做数据类型优先。你可能应该仔细阅读一下。谢谢@JNK——我理解为什么会发生这种情况——只是希望在需要的时候找到一种更方便的方法来消除(DTP)障碍。无论如何,我应该提到它,所以我将编辑这个问题。我可能在这里遗漏了一些东西,但我只是不知道除了空值之外,这将如何失败<代码>选择[FirstName]+'+[LastName]
。空值由
isnull
处理。在这里测试。这就是SQL Server 2008。如果你有一个int字段,你当然必须先将它转换。您不需要强制转换包含int的varchar字段,或者更确切地说是字符1。同意Mikael的说法,
varchar
列中存储的
1
不会像您建议的那样引起任何问题。@JNK:很抱歉第一个答案非常简洁,我只是尝试先发布它:)@a1ex07-至少您已经修复了它。不用担心……这听起来真的很好——我正在仔细阅读,我想这会导致在存储过程中重新编译(这就是我要做的),他们建议在存储过程中使用isnull()
/*  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 */