【问题标题】:SQL Server concatenation not working with plusSQL Server 连接不适用于加号
【发布时间】:2016-03-10 08:39:33
【问题描述】:

我正在尝试使用“+”连接两个字符串,这两个字符串都派生自一个子字符串,每个子字符串都从不允许空值的 ntext 字段转换为 varchar(20)。

当我运行代码时,它只取两个字符串中的第一个,而忽略第二个,因此连接不成功。知道我在这里做错了什么或遗漏了什么吗?

    Select  Top 100
            Substring(Cast(w.WO_Type_Field_02 As nvarchar(20)), 1, 20) As PossFirst,

            Substring(Cast(w.WO_Type_Field_04 As nvarchar(20)), 1, (20 - 
                Len(Substring(Cast(w.WO_Type_Field_02 As nvarchar(20)), 1, 20)) + 1)) As PossLast, 

            Substring(Cast(w.WO_Type_Field_02 As nvarchar(20)), 1, 20) +
            Substring(Cast(w.WO_Type_Field_04 As nvarchar(20)), 1, (20 - 
                Len(Substring(Cast(w.WO_Type_Field_02 As nvarchar(20)), 1, 20)) + 1)) As PossLogin

    from    V_WOI_WorkOrder w

我得到的是以下内容:

PossFirst   PossLast    PossLogin
----------- ----------- -----------
james       roberts     james
mark        smith       mark
harry       chapman     harry

我应该得到的是:

PossFirst   PossLast    PossLogin
----------- ----------- -----------
james       roberts     jamesroberts
mark        smith       marksmith
harry       chapman     harrychapman

我的子字符串中的 len 的原因是完整的串联长度不应超过 20 个字符,我还没有完成那部分,但我认为这与我的串联失败无关。

Screenshot of results

【问题讨论】:

  • 我们需要数据库模式、样本数据和期望输出。您只提供最后一部分。
  • 架构是 dbo,数据只是组织内大约 300k 个人的名字和姓氏的列表。名称中不允许使用除连字符以外的特殊字符,但它们均已从不允许空值的 ntext 字段转换为 varchar(20)。
  • 模式意味着数据库结构。我们仍然需要查看数据。您应该提供一个 Minimal Complete 示例。
  • 请原谅我的无知胡安卡洛斯,我不清楚你所说的数据库结构是什么意思。如果你想让我运行 select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'V_WOI_WorkOrder' 恐怕返回的数据是巨大的。再次为我的无知感到抱歉
  • 我在返回的数据上方添加了一张图片

标签: sql-server concatenation string-concatenation


【解决方案1】:

嗯,我还不确定这个问题,但我们可以尝试这样做..

SELECT PossFirst, PossLast, ISNULL(PossFirst,'') + ISNULL(PossLast,'') AS PossLogin FROM (
       Select
            Convert(nvarchar(20),Substring(Cast(w.WO_Type_Field_02 As nvarchar(20)), 1, 20)) As PossFirst,
            Convert(nvarchar(20),Substring(Cast(w.WO_Type_Field_04 As nvarchar(20)), 1, (20 - 
                Len(Substring(Cast(w.WO_Type_Field_02 As nvarchar(20)), 1, 20)) + 1))) As PossLast, 
    from V_WOI_WorkOrder w
   ) AS T

编辑:这很奇怪,我有这张桌子

并尝试过

select PossFirst, PossLast, PossFirst + PossLast from (
select
    Substring(Cast(w.firstname As nvarchar(20)), 1, 20) As PossFirst
    , Substring(Cast(w.lastname As nvarchar(20)), 1, (20 - 
                Len(Substring(Cast(w.lastname As nvarchar(20)), 1, 20)) + 1)) As PossLast
    from nTextDataTypeTest w
) AS T

有了这个结果...

我想知道你有哪些列数据类型,我想知道你使用的是什么 SQL 版本..

编辑:让我们尝试修剪它们..

SELECT PossFirst, PossLast, ISNULL(PossFirst,'') + ISNULL(PossLast,'') AS PossLogin FROM (
           Select
                Rtrim(Ltrim(Convert(nvarchar(20),Substring(Cast(w.WO_Type_Field_02 As nvarchar(20)), 1, 20)))) As PossFirst,
                Rtrim(Ltrim(Convert(nvarchar(20),Substring(Cast(w.WO_Type_Field_04 As nvarchar(20)), 1, (20 - 
                    Len(Substring(Cast(w.WO_Type_Field_02 As nvarchar(20)), 1, 20)) + 1))))) As PossLast, 
        from V_WOI_WorkOrder w
       ) AS T

【讨论】:

  • 感谢您的回复,我已经尝试过了,但是当第二个字符串没有连接到第一个字符串时,我仍然得到相同的结果。这很奇怪,这是我第一次看到这种情况发生并且过去没有遇到过串联问题。我觉得这可能是因为原始字段是 ntext
  • 谢谢肯,这也没有奏效。不过,为您的编辑干杯。
  • 我们可以扩展一下,我们可以看看你的表结构吗?
  • 这是我在这些字段上的内容:COLUMN_NAME - DATA_TYPE - IS_NULLABLE - CHARACTER_SET_NAME - COLLATION_NAME WO_Type_Field_02 [ntext] NOT NULL, UNICODE - Latin1_General_CI_AS WO_Type_Field_04 [ntext] NOT NULL, UNICODE - Latin1_General_CI_AS
  • 嘿,乔迪,您介意使用我的最新编辑吗?看来我们还没有尝试修剪字段..
【解决方案2】:

这里的问题是您的 ntext 字段包含空格。这些隐藏的字符正在占用您 20 个字符的限制。

有两种简单的方法可以发现空白。您可以使用 LEN 函数和/或连接前导字符和尾随字符。

我使用表变量创建了一个关于堆栈数据交换的示例(下面的链接和代码)。这种方法的好处是我们可以共享相同的代码。

在本例中,james 后缀有许多空格。其他记录没有。如您所见,詹姆斯返回时没有姓氏。其他人不是。发生这种情况是因为空格计入 20 个字符的限制。使用 RTRIM 将删除这些。

SQL Server 中的 RTRIM 仅适用于空格。如果您的空格是由其他控制字符组成的,您将需要不同的方法。

我已将 SUBSTRING 替换为 LEFT,这样可以用更少的步骤实现相同的结果。

编辑 1:包括原始问题和解决方案的描述。

编辑 2:在 OPs 问题解决后重写了答案。新答案更好地解释了问题和解决方案。

Example

/* Let's make a variable that we can all share.
 */
DECLARE @SampleData TABLE
   (
      FirstName    NTEXT    NOT NULL,
      LastName    NTEXT    NOT NULL
   )
;
   

/* Populate the table with sample values for us
 * to experiment with.
 * Postfix james with blank spaces.
 */
INSERT INTO @SampleData
   (
      FirstName,
      LastName
   )
VALUES
   ('james                         ', 'roberts'),
   ('mark', 'smith'),
   ('harry', 'chapman')
;
   

/* CAST and CONCATENATE the NTEXT fields.
 * SUBSTRING replaced with LEFT for simplicity.
 * Pipe added to end of each string to show its length.
 */
SELECT
   FirstName,
   LastName,
   LEFT(CAST(FirstName AS NVARCHAR(20)) + CAST(LastName AS NVARCHAR(20)), 20) + '|'             AS FirstLastName_NoTRIM,
    LEFT(RTRIM(CAST(FirstName AS NVARCHAR(20))) + RTRIM(CAST(LastName AS NVARCHAR(20))), 20) + '|'  AS FirstLastName_WithTRIM
FROM
   @SampleData
;

【讨论】:

  • 谢谢,我已经运行了这个以及其他提交,如果我对源自类型 nvarchar 或 varchar 的字段运行它们,则会发生连接并且这些工作成功。反过来,当我针对从 ntext 派生的字段运行这些中的任何一个时,它们只生成 FirstName 并且无法连接 LastName ...我已经针对数据库中的多个 ntext 字段进行了测试,以确保我涵盖了所有选项。正如你所说,我还检查了任何前导或尾随空格,但没有。真的很纠结这个,很奇怪。
  • 当你运行这个时,你看到詹姆斯的第一张唱片是什么? FirstLastName_NoTRIM 列应该只显示 ames,而 FirstLastName_WithTRIM 应该包含 jamesroberts。
  • 还建议您尝试 SELECT Cast(w.WO_Type_Field_02 As nvarchar(20)) + '*'。最后的星号将在视觉上突出显示任何空格/特殊字符。最后,您还应该尝试 SELECT LEN(CAST(w.WO_Type_Field_02 As nvarchar(20)))。如果返回 20,则在名称之后存在某种形式的空格。
  • 你是对的,我们有一个行之有效的解决方案。场上的有效 len 比可见的多出 1 个字符。如果我然后按如下方式修剪 len: Cast(SUBSTRING(w.WO_Type_Field_02,1,(Len(w.WO_Type_Field_02)-1)) As varchar(20)) As PossFirst 它会产生允许连接的结果。我连接到这个作品的任何东西。谢谢!您希望我如何完成此操作以突出其他遇到此问题的人的答案?
  • 非常感谢!也祝你圣诞快乐
【解决方案3】:

使用 nText 或最初从 nText 字段派生的 varchar 字段的天气,字符的视觉计数与字符上的 Len 总共相差 1 个字符。

字符的视觉计数显示例如 12 个字符。 [field] 上的 len 显示 13 个字符,因此当我将 [field] 子串到 len[field]-1 时,如下所示,我可以连接到它。

    SUBSTRING([Field], 1, (Len([Field]) - 1)

我们所做的是修剪掉阻止我们串联工作的尾随隐藏/特殊字符。

    CAST(SUBSTRING([Field], 1, (Len([Field]) - 1) As varchar(20))

然后我们将结果转换为 varchar,以匹配我们希望连接的其他字段。

我现在有了使用下面的字段和表格的最终代码,它可以成功运行!

    Select  Cast(SUBSTRING(w.WO_Type_Field_02,1,(Len(w.WO_Type_Field_02)-1)) As varchar(20)) As PossFirst,
            Substring(Cast(w.WO_Type_Field_04 As nvarchar(20)), 1, (20 - 
                Len(Substring(Cast(w.WO_Type_Field_02 As nvarchar(20)), 1, 20)) + 1)) As PossLast,
            Cast(SUBSTRING(w.WO_Type_Field_02,1,(Len(w.WO_Type_Field_02)-1)) As varchar(20)) + '.' +
            Substring(Cast(w.WO_Type_Field_04 As nvarchar(20)), 1, (20 - 
                Len(Substring(Cast(w.WO_Type_Field_02 As nvarchar(20)), 1, 20)) + 1)) As PossLogin  
    from    V_WOI_WorkOrder w

【讨论】:

    猜你喜欢
    • 2018-12-27
    • 2017-03-04
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 2017-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多