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

时间:2019-12-06 11:05:08

标签: php sql-server doctrine-orm

我正在使用Doctrine 2界面访问MS SQL数据库。我发现了双方都很有趣的问题:教义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更改为带有“ +”的表达式。但这工作正常(或看起来确实如此),直到我想将隐含字符串与其他表中的值进行比较...

$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);

(我正在从内存中写此查询,如果有什么问题-没关系-是为了可视化问题) 使用CONCAT函数在SQL Studio中执行原始查询绝对可以正常工作。带有“ +”的不是。所有具有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 c
FROM 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”列始终正确。

2 个答案:

答案 0 :(得分:1)

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

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

示例:

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级状态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 ). Finally you have NULL + 7 = NULL , which is fine as NULL can be implicitly converted to an int`。

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

答案 1 :(得分:0)

CONCAT和'+'都不同。 在mysql concat中,简单地组合/加入我们的数据/设置/编号。 主要区别在于数据类型。