为了账号安全,请及时绑定邮箱和手机立即绑定

MS SQL CONCAT 与“+”查询的区别(使用 Doctrine 2)

MS SQL CONCAT 与“+”查询的区别(使用 Doctrine 2)

PHP
湖上湖 2022-06-11 18:03:27
我正在使用 Doctrine 2 接口访问 MS SQL 数据库。我发现双方都非常有趣的问题:Doctrine 2 和 MS SQL。Doctrine 2 出于某种原因更改查询$this->getEntityManager()->createQueryBuilder()            ->from(table::class, 'il')            ->select('CONCAT(il.col1,il.col2,il.col3) AS concated')更改为类似(它使用自己的别名):SELECT (t0_.col1+ t0_.col2+ t0_.col3) AS sclr_0 FROM tableName t0_最重要的 - 它CONCAT用“+”改变了 into 表达式。但它工作正常(或者看起来确实如此),直到我想将连接字符串与其他表中的值进行比较......$targetQueryBuilder->getEntityManager()->createQueryBuilder()            ->from($namespace, 's')            ->select('1')            ->where('CONCAT(il1.col1, il1.col2, il1.col3) = s.controlValue')            ->andWhere('s.tableName = :tablename')            ->andWhere('s.tableRowIdentifier='.$rowIdentifier);(我正在从内存中编写此查询,如果有问题 - 没关系 - 这是为了将问题可视化)在 SQL Studio 中执行原始查询对CONCAT函数来说非常有效。使用“+”则不然。所有具有 nvarchar 类型的连接列。问题是:差异在哪里?我检查了学说中的大量组合以跳过映射CONCAT到“+”但没有成功,我不得不编写一些虚拟词法分析器扩展来强制将CONCAT函数应用于最终查询。其他(可能是特定于 ms sql server)的问题是:当我在测试时SELECT(i1_.NameUnternehmen + i1_.Land + i1_.Ort + i1_.Straße + i1_.Postleitzahl) AS a,CONCAT(i1_.NameUnternehmen , i1_.Land , i1_.Ort , i1_.Straße , i1_.Postleitzahl) AS cFROM tablename(Straße在这个问题中,列名看起来并不重要)当使用 WHERE 语句将连接字符串与控制值进行比较时,选择结果是不同的。->where('CONCAT(il1.col1, il1.col2, il1.col3) = s.controlValue')- 一切都是正确的->where('(il1.col1 + il1.col2 + il1.col3) = s.controlValue')- 列“a”中的结果为空。我刚刚测试过,在其他表上它有时不为空。我不知道为什么。“c”列总是正确的。
查看完整描述

1 回答

?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

CONCAT并且+不要操作相同。如果任何表达式NULL在使用时具有值+,NULL则将返回。对于CONCAT,它将隐式替换NULL为'',因此NULL不会返回。


CONCAT还会将表达式中的任何值隐式转换为(n)varchar,其中 as+使用数据类型优先级来确定数据类型,并将表达式中的其他值隐式转换为最高优先级的数据类型。


例子:


SELECT c1,

       c2,

       c3,

       c4,

       c1 + c2 + c3 + c4, --NULL 

       CONCAT(c1, c2, c3, c4) --'abcdefxyc'

FROM (VALUES('abc','def',NULL,'xyz'))V(c1, c2, c3, c4);

隐式转换:


SELECT c1 + c2 + c3 + c4

FROM (VALUES('abc','def',7,'xyz'))V(c1, c2, c3, c4);

消息 245,级别 16,状态 1,第 9

行将 varchar 值“abcdef”转换为数据类型 int 时转换失败。


SELECT CONCAT(c1, c2, c3, c4) --'abcdef7xyz'

FROM (VALUES('abc','def',7,'xyz'))V(c1, c2, c3, c4);

有趣但预期的行为:


SELECT c1 + c2 + c3 + c4 --NULL

FROM (VALUES('abc','def',NULL,7))V(c1, c2, c3, c4);


SELECT c1 + c2 + c3 + c4 --123456790

FROM (VALUES('123','456','789',1))V(c1, c2, c3, c4);

这种行为的原因是因为表达式是从左到右计算的。对于第一个,因此您有'abc' + 'def' = 'abcdef'( 'abcdef' + NULL = NULL) varchar。最后你有了NULL + 7 = NULL,这很好,NULL可以隐式转换为int.


对于后者,你有'123' + '456' = '123456'then '123456' + '789' = '123456789'。最后你有'123456789' + 1 = 123456789 + 1 = 123456790. 请注意,在最终表达式中,varchar首先隐式转换为 a int,然后+运算符充当加法,而不是串联。


查看完整回答
反对 回复 2022-06-11
  • 1 回答
  • 0 关注
  • 114 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信