SQL从SQL结果中删除自由文本中的字符

时间:2016-07-14 11:52:20

标签: sql sql-server

enter image description here我试图从名为NOTE_DESC的列中删除数字。如果字符有数字,则应填充SPECIAL列。如果没有别的,JUNK列应该有我想要擦除的特殊字符。但是我得到的变量显示SPECIAL与NOTE_DESC相同,而JUNK列为空或空。

IF OBJECT_ID('tempdb.dbo.#DUPE_SUSPECT', 'U') IS NOT NULL
  DROP TABLE #DUPE_SUSPECT

SELECT
  ROW_NUMBER() OVER (ORDER BY CAST(NOTE_DESC AS varchar)) AS ROW_NUM,
  [NOTE_ID],
  CAST([NOTE_DESC] AS varchar) [NOTE_DESC],
  CASE
    WHEN CHARINDEX('PEND KEY', CAST([NOTE_DESC] AS varchar)) > 0 THEN SUBSTRING(CAST([NOTE_DESC] AS varchar), CHARINDEX('PEND KEY', CAST([NOTE_DESC] AS varchar)), 24)
    WHEN CHARINDEX('"MACESS WORK ITEM(S):', CAST([NOTE_DESC] AS varchar)) > 0 THEN SUBSTRING(CAST([NOTE_DESC] AS varchar), CHARINDEX('"MACESS WORK ITEM(S):', CAST([NOTE_DESC] AS varchar)), 38)
    WHEN LEFT(CAST([NOTE_DESC] AS varchar), 2) = 'PK' THEN LEFT(CAST([NOTE_DESC] AS varchar), 18)
    WHEN LEFT(CAST([NOTE_DESC] AS varchar), 1) NOT LIKE '%[A-Z]%' AND
      LEFT(CAST([NOTE_DESC] AS varchar), 1) NOT IN ('...', ',,:', ':', '.', '!', ',', '?') THEN LEFT(CAST([NOTE_DESC] AS varchar), 18)
    ELSE ''
  END [SPECIAL],
  [CREATED_BY_ID],
  [CREATED_TIMESTAMP],
  [CREATED_TEAM_ID],
  [SERV_CCP_INQ_KEY],
  [ACTION_TIMESTAMP] INTO #DUPE_SUSPECT
FROM [dbo].[Staging_CCP_SERVICE_INQ_NOTES]
WHERE CREATED_TIMESTAMP IS NOT NULL

ALTER TABLE #DUPE_SUSPECT
ADD JUNK varchar(max) NULL

SELECT
  *
FROM #DUPE_SUSPECT
ORDER BY ROW_NUM

-- Create the variables used in parsing the string

DECLARE @count int,
        @position int,
        @strText char(5000),
        @row_num int,
        @x int,
        @pend_key char(20),
        @character char(1),
        @junk char(5000);

-- Initialize the variables.  
SET @count = 100
SET @row_num = 1
SET @position = 1;

WHILE @row_num < @count
BEGIN
  SET @strText = (SELECT
    [NOTE_DESC]
  FROM #DUPE_SUSPECT
  WHERE ROW_NUM = @row_num)

  WHILE @position < LEN(@strText)
  BEGIN
    SET @character = SUBSTRING(@strText, @position, 1)
    IF @character IN ('1', '2', '3', '4', '5', '6', '7', '8', '9')
    BEGIN
      SET @pend_key = @pend_key + @character
    END
    ELSE
    BEGIN
      SET @junk = @junk + @character

    END
    SET @position = @position + 1
  END
  UPDATE #DUPE_SUSPECT
  SET SPECIAL = @pend_key,
      JUNK = @junk
  WHERE ROW_NUM = @row_num
  SET @row_num = @row_num + 1
  SET @position = 1
  SET @pend_key = ''
END

1 个答案:

答案 0 :(得分:0)

如果没有示例数据和表结构,几乎不可能弄清楚代码在做什么,但我可以看到WHILE循环位中代码的几个(可能的)问题。

  1. @pend_key和@junk被声明为固定长度的字符,因此你附加到它们的代码将永远无法工作(字符被填充到它们的全长,所以无论你追加什么都会溢出)。
  2. 在任何情况下,它们都会以NULL值开头,因此无论如何都不能在它初始化之前附加它。
  3. 所以改变他们的声明并将它们初始化为空字符串,如下所示:

    DECLARE @pend_key varchar(20),
            @junk varchar(5000);
    
    SET @pend_key = ''
    SET @junk = ''
    

    如果您正在使用SQL Server 2008 +,则可以在其中声明并初始化,例如: DECLARE @pend_key varchar(20) = '';

    1. 您正在迭代@strText变量,该变量最多可达5000个字符,但是将数字附加到@pend_key,只有20个字符长。这可能是一个错误,至少浪费了很多时间。

    2. 在循环结束时,为下一行重置@pend_key的值,但不要对@junk执行相同的操作,以便它继续填充前一行中的字符(至少直到它为止)达到5000长)。我怀疑你是否打算这样做。

    3. 尝试修复这些问题,您的代码可能会更好 - 正如我所说,没有样本数据真的很难说!

      在任何情况下,逐个字符地迭代数据,逐行都是非常低效的,并且除非您的数据集很小,否则将永远消失。

      几乎可以肯定,这是一种更好的方式来做你想做的事情。