【问题标题】:SQL server update fields from a concatenated string in a fieldSQL Server 从字段中的连接字符串更新字段
【发布时间】:2016-10-17 15:31:45
【问题描述】:

我对写入数据库的 SQL 代码相当陌生。我一直在尝试自己编写这段代码,但我运气不佳。特别是因为我真的不知道如何在没有实际写入数据库的情况下测试它 我有一个包含 5 个 UDF 字段的数据库。 'UDF1-UDF5'。我工厂的操作员应该将条形码扫描到特定的条形码字段中,该字段将条形码分成五个字段(它们都是 char(30) 字段)。不幸的是,他们正在直接扫描 UDF1 字段,因此整个条形码字符串都在一个字段中。 (我无法控制这个软件)我正在尝试编写一个脚本来解析数据库,将这些字段拆分为单独的变量并更新数据库。我可以使用一些帮助,因为我认为我需要动态 SQL 来执行此操作,但我对此了解不多。以下是有关该系统的更多信息。

条形码字段如下所示:

%2S12345%1%1%0%10%

'%' 字符开始和结束条形码并连接字符的位置。第一个 UDF 字段“2”的第一个字符是校验位,并且始终相同。 第一个字段始终为 5 或 6 个字符(不包括校验位),其余为 1 或 2 位。如果条形码只有前三个字段,我还需要不会中断的代码。这里没有太多的一致性。部分条码被截断。

问题,

    1234563信息。有没有更简单的方法?
  1. 有时我必须有条件地设置变量,但我似乎无法让设置命令工作。我理解为什么这样的事情不起作用,但我不知道有任何其他方法可以做到这一点。

.

 DECLARE @BASEID CHAR(30), @LOTID CHAR(30), @SPLITID CHAR(30), @SUBID CHAR(30), @SEQUENCENO CHAR(30), @BASELEN INT
 SET @BASELEN =
    CASE WHEN(
        SELECT ISNUMERIC(SUBSTRING(R.UDF1,3,1))
        FROM VISION17SLITTER.DBO.ROLLINFO R 
        WHERE R.UDF1 LIKE '[%]%'
        ) = 1
        THEN 5
        ELSE 6
    END

3。一旦我可以得到变量集,我假设一个简单的条件更新语句会起作用,但是如果在尝试之前我应该​​知道其他任何事情,我将不胜感激。

再次感谢,

【问题讨论】:

  • 听起来你需要一个字符串拆分器。这里有几个很棒的选择。 sqlperformance.com/2012/07/t-sql-queries/split-strings 或者,如果您使用的是 sql server 2016,则内置了一个不错的新闪亮。 msdn.microsoft.com/en-us/library/mt684588.aspx
  • 感谢您的链接,不幸的是我不是数据库管理员(好像这并不明显:)),实现类似的东西可能很困难。
  • 获取字符串拆分器应该非常简单。特别是如果您与 DBA 交谈并告诉他们另一个选择是使用带有动态 sql 的循环。如果没有分离器,这将是可怕的组合。
  • 还是去问问 dba。

标签: sql sql-server concatenation


【解决方案1】:

考虑以下几点:

Declare @YourTable table (ID int,BarCode varchar(100))
Insert Into @YourTable values
(1,'%2S12345%1%1%0%10%'),
(2,'%ABC1234%2%3%4%50%')

Select A.ID
      ,A.BarCode
      ,B.*
 From  @YourTable A
 Cross Apply (
                Select Pos1 = xDim.value('/x[1]','varchar(max)')
                      ,Pos2 = xDim.value('/x[2]','varchar(max)')
                      ,Pos3 = xDim.value('/x[3]','varchar(max)')
                      ,Pos4 = xDim.value('/x[4]','varchar(max)')
                      ,Pos5 = xDim.value('/x[5]','varchar(max)')
                      ,Pos6 = xDim.value('/x[6]','varchar(max)')
                      ,Pos7 = xDim.value('/x[7]','varchar(max)')
                      ,Pos8 = xDim.value('/x[8]','varchar(max)')
                      ,Pos9 = xDim.value('/x[9]','varchar(max)')
                 From (Select Cast('<x>' + Replace(A.BarCode,'%','</x><x>')+'</x>' as XML) as xDim) A

             ) B 

退货

现在,您可能会注意到 Pos1 和 Pos7 是空白的。这是因为您的字符串以分隔符开头和结尾。如果您想这样定制 CROSS APPLY:

Select Pos1 = xDim.value('/x[2]','varchar(max)')
      ,Pos2 = xDim.value('/x[3]','varchar(max)')
      ,Pos3 = xDim.value('/x[4]','varchar(max)')
      ,Pos4 = xDim.value('/x[5]','varchar(max)')
      ,Pos5 = xDim.value('/x[6]','varchar(max)')
 From (Select Cast('<x>' + Replace(A.BarCode,'%','</x><x>')+'</x>' as XML) as xDim) A

哪个返回

【讨论】:

  • 我写了一个与你在这里的脚本非常相似的脚本。我能够删除前导字符和尾随字符,并将所有内容拆分为 1-5 位。我的问题是,如何将其重新应用于我的实际数据库?我尝试用更新语句替换 select 语句,但我不确定如何访问交叉应用的信息。
  • @mreff555 查看我刚刚添加的第二个答案
【解决方案2】:

创建一个函数来分割你的字符串

CREATE FUNCTION [dbo].[fnSplitString] 
( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
) 
BEGIN 
    DECLARE @start INT, @end INT 
    SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
    WHILE @start < LEN(@string) + 1 BEGIN 
        IF @end = 0  
            SET @end = LEN(@string) + 1

        INSERT INTO @output (splitdata)  
        VALUES(SUBSTRING(@string, @start, @end - @start)) 
        SET @start = @end + 1 
        SET @end = CHARINDEX(@delimiter, @string, @start)

    END 
    RETURN 
END

然后删除前两个控制字符,最后一个控制字符并像这样调用函数

select * from dbo.fnSplitString('S12345%1%1%0%10','%')

然后该函数将返回具有以下值的表:

splitdata
=========
S1234
1
1
0
10

【讨论】:

  • 查看 Sean Lange 的评论和链接。您将看到性能的显着提升。 sqlperformance.com/2012/07/t-sql-queries/split-strings
  • CLR方法可能更快,但需要本地访问服务器才能安装dll。另一方面,我提供的解决方案不需要数据库管理员的额外权限。
  • 谢谢,拆分函数按描述工作,但我很难理解如何将数据列表放入该函数。
猜你喜欢
  • 1970-01-01
  • 2010-12-09
  • 1970-01-01
  • 2015-08-15
  • 2018-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多