【问题标题】:SQL Server String Concatenation with NullSQL Server 字符串连接与 Null
【发布时间】:2011-02-24 09:34:02
【问题描述】:

我正在跨字段创建一个计算列,其中一些字段可能为空。

问题是,如果这些字段中的任何一个为空,则整个计算列将为空。我从 Microsoft 文档中了解到这是预期的,可以通过设置 SET CONCAT_NULL_YIELDS_NULL 来关闭。但是,我不想更改此默认行为,因为我不知道它对 SQL Server 其他部分的影响。

有没有办法让我只检查一列是否为空,如果它不为空,只在计算列公式中附加其内容?

【问题讨论】:

  • 在提出问题时接受的答案是正确的,但对于 SQL Server 2012 及更高版本上的每个人(这个阶段应该是每个人)@Martin-Smiths 的答案是最好的,因为它可以处理自动为空。

标签: sql-server null string-concatenation calculated-columns


【解决方案1】:

你可以使用ISNULL(....)

SET @Concatenated = ISNULL(@Column1, '') + ISNULL(@Column2, '')

如果列/表达式的值确实为 NULL,则将使用指定的第二个值(此处为空字符串)。

【讨论】:

  • "Coalesce" 是 ANSI 标准的函数名,但 ISNULL 更容易拼写。
  • 而且 ISNULL 在 SQL Server 上似乎也快了一点 - 因此,如果您想在将字符串连接到计算列的函数中使用它,您可能会放弃 ANSI 标准并选择速度(见 Adam Machanic:sqlblog.com/blogs/adam_machanic/archive/2006/07/12/…
  • 刚刚使用了这个 Isnull(,) 查询,当我将值连接在一起时,它非常有用,如果其中一个为 null,那么所有内容也都为 null。
  • 使用ISNULL() 是一个很好的解决方案,但是从SQL Server 2012 开始,您也可以使用CONCAT 函数来获得相同的结果:CONCAT(@Column1, @Column2)
  • 这里值得注意的是,如果你想将null换成非空字符串,即IsNull(@Column1, 'NULLVALUE'),换成IsNull,则替换字符串的长度限制为列的长度它正在替换,而不是 Coalesce
【解决方案2】:

从 SQL Server 2012 开始,使用 CONCAT 函数变得更加容易。

它将NULL 视为空字符串

DECLARE @Column1 VARCHAR(50) = 'Foo',
        @Column2 VARCHAR(50) = NULL,
        @Column3 VARCHAR(50) = 'Bar';


SELECT CONCAT(@Column1,@Column2,@Column3); /*Returns FooBar*/

【讨论】:

  • 对于旧版本,您会得到“'CONCAT' 不是可识别的内置函数名称”,因此请使用 COALESCE
  • @Savage - COALESCE 不起作用,因为它不连接,它只返回第一个非空参数
【解决方案3】:

使用COALESCE。而不是your_column 使用COALESCE(your_column, '')。这将返回空字符串而不是 NULL。

【讨论】:

  • OP 想要将字符串连接在一起,COALESCE 不会这样做
  • @codeulike 您将使用它来将 null 替换为空字符串,然后将其结果与旧字符串连接运算符 (+) 一起使用 - 与接受的答案相同ISNULL
【解决方案4】:

您也可以使用 CASE - 我下面的代码会同时检查空值和空字符串,并且仅在有要遵循的值时才添加分隔符:

SELECT OrganisationName, 
'Address' = 
CASE WHEN Addr1 IS NULL OR Addr1 = '' THEN '' ELSE Addr1 END + 
CASE WHEN Addr2 IS NULL OR Addr2 = '' THEN '' ELSE ', ' + Addr2 END + 
CASE WHEN Addr3 IS NULL OR Addr3 = '' THEN '' ELSE ', ' + Addr3 END + 
CASE WHEN County IS NULL OR County = '' THEN '' ELSE ', ' + County END 
FROM Organisations 

【讨论】:

  • 我标记了它,但我现在认为它有问题:如果第一个字符串 Addr1 为 NULL 或空,而第二个或第三个或第四个字符串 Addr2 或 Addr3 或 County 是不是,那么地址将以不必要的逗号开头。可惜,我喜欢这个想法和清晰:(
  • ...但您可以使用 TRIM() 来解决这个问题(删除前导和尾随逗号)。例如我正在使用 SQL 变量并使用如下内容: SET @strAddress = TRIM(',' FROM @strAddress)
【解决方案5】:

使用

SET CONCAT_NULL_YIELDS_NULL  OFF 

空值与字符串的连接不会产生空值。

请注意,这是一个已弃用的选项,请避免使用。 有关详细信息,请参阅documentation

【讨论】:

    【解决方案6】:

    如果有人在寻求帮助在字符串之间添加分隔符时,我只是想贡献一下,这取决于字段是否为 NULL

    因此,在从单独的字段创建单行地址的示例中

    Address1Address2Address3CityPostCode

    就我而言,我有以下计算列,它似乎可以按我的意愿工作:

    case 
        when [Address1] IS NOT NULL 
        then (((          [Address1]      + 
              isnull(', '+[Address2],'')) +
              isnull(', '+[Address3],'')) +
              isnull(', '+[City]    ,'')) +
              isnull(', '+[PostCode],'')  
    end
    

    希望对某人有所帮助!

    【讨论】:

    • 那里有很多多余的嵌套括号可以删除。另一个提示是,您还可以删除 case 语句,就好像 address1 为 null 一样,整个表达式将评估为 null(尽管有 case 语句确实会引起注意,这可能会发生)
    【解决方案7】:

    ISNULL(ColumnName, '')

    【讨论】:

      【解决方案8】:

      我也遇到了很多麻烦。无法使用上面的案例使其正常工作,但这对我有用:

      Replace(rtrim(ltrim(ISNULL(Flat_no, '') + 
      ' ' + ISNULL(House_no, '') + 
      ' ' + ISNULL(Street, '') + 
      ' ' + ISNULL(Town, '') + 
      ' ' + ISNULL(City, ''))),'  ',' ')
      

      Replace 纠正了由于连接单个空格而导致的双空格,它们之间没有任何内容。 r/ltrim 去掉末尾的任何空格。

      【讨论】:

        【解决方案9】:

        在 Sql Server 中:

        insert into Table_Name(PersonName,PersonEmail) values(NULL,'xyz@xyz.com')
        
        PersonName is varchar(50), NULL is not a string, because we are not passing with in single codes, so it treat as NULL.
        

        代码隐藏:

        string name = (txtName.Text=="")? NULL : "'"+ txtName.Text +"'";
        string email = txtEmail.Text;
        
        insert into Table_Name(PersonName,PersonEmail) values(name,'"+email+"')
        

        【讨论】:

          【解决方案10】:

          此示例将帮助您在创建插入语句时处理各种类型

          select 
          'insert into doc(Id, CDate, Str, Code, Price, Tag )' + 
          'values(' +
                '''' + convert(nvarchar(50), Id) + ''',' -- uniqueidentifier
              + '''' + LEFT(CONVERT(VARCHAR, CDate, 120), 10) + ''',' -- date
              + '''' + Str+ ''',' -- string
              + '''' + convert(nvarchar(50), Code)  + ''',' -- int
              + convert(nvarchar(50), Price) + ',' -- decimal
              + '''' + ISNULL(Tag, '''''') + '''' + ')'  -- nullable string
          
           from doc
           where CDate> '2019-01-01 00:00:00.000'
          

          【讨论】:

            猜你喜欢
            • 2011-12-25
            • 2016-06-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-11
            • 2016-10-10
            • 2017-05-11
            相关资源
            最近更新 更多