替换我的数据中的特定部分

时间:2018-01-08 21:59:36

标签: sql sql-server

我想知道更换一些数字的最有效和最安全的方法。在我的表中,我有两列:Nummer和Vater。在Nummer专栏中,我存储了文章编号。结尾为.1的文章是'main'文章,其余是combinations(有时主文章不包含组合),所有具体内容都将其作为具有组合的具体产品。数字由 3个部分(由3个点(始终)分隔)组成。对所有人来说,Vater总是主要的文章编号,如下所示:

示例1:

Nummer        |   Vater
-------------------------------
003.10TT032.1   |  003.10TT032.1
003.10TT032.2L  |  003.10TT032.1
003.10TT032.UY  |  003.10TT032.1

Nummer column = varchar Vater column = varchar

我希望有可能更改前两部分n.n

例如我想说并通过sql查询发送我要替换为:9.4R53因此根据我们的示例,最终结果应如下所示:

Nummer    |   Vater
----------------------
9.4R53.1   |  9.4R53.1
9.4R53.2L  |  9.4R53.1
9.4R53.UY  |  9.4R53.1

示例2:

电流:

Nummer        |   Vater
-------------------------------
12.90D.1    |  12.90D.1 
12.90D.089  |  12.90D.1 
12.90D.2    |  12.90D.1 

替换为:829.12

结果应该是:

Nummer        |   Vater
-------------------------------
829.12.1    |  829.12.1 
829.12.089  |  829.12.1 
829.12.2    |  829.12.1 

我的查询如下:

示例1查询:

update temp SET Nummer = replace(Nummer, '003.10TT032.', '9.4R53.'),
                            Vater = replace(Vater, '003.10TT032.1', '9.4R53.1')
                            WHERE Vater = '003.10TT032.1'

示例2查询:

update temp SET Nummer = replace(Nummer, '12.90D.', '829.12.'),
                            Vater = replace(Vater, '12.90D.1', '829.12.1')
                            WHERE Vater = '12.90D.1 '

在我的数据库中,我有记录,因此我想确保此查询没有问题,并且没有任何可能导致错误结果的内容。请告诉您是否可以这样。

因此问题:

  1. 根据我的文章存储方式,此查询是否正常? (希望避免错误的替换,这可能会导致生产数据库数据混乱)

  2. 有更好的解决方案吗?

2 个答案:

答案 0 :(得分:1)

回答你的问题:是的,你的解决方案是有效的,是的,有一些东西可以使它成为防弹的。使其成为防弹和可逆的是我建议在下面做的。如果你知道的话,你会睡得更好 A.回答任何愤怒的人问你的问题"你对我的产品表做了什么" B.知道你可以撤销你对此表所做的任何更改(无需恢复备份),包括其他人的错误(如错误的指示)。

因此,如果你真的必须对输出有100%的信心,我就不会一次性运行它。我建议在单独的表中准备查询,然后在动态SQL的循环中运行查询。

这有点麻烦,但您可以这样做:创建一个包含所需列的专用表(如batch_id,insert_date等)和一个名为execute_query NVARCHAR(MAX)的列。 然后通过在源表中运行需要替换的部分的select distinct来加载表(使用CHARINDEX找到第二个点 - 使CHARINDEX从第一个点的CHARINDEX开始+ 1获得第二个点)。

换句话说:您逐个准备所有查询(例如示例中的查询)并将它们存储在表格中。

如果您想要完全安全,更新查询可以包括n和n之间的源table_id。 (您在源表上使用GROUP BY构建)。如果您以后必须回答问题,这将确保您可以跟踪已更新的记录。

完成此操作后,您将运行一个循环,逐个执行每一行。 此方法的优点是跟踪您的更改 - 您还可以在准备更新查询的同时准备回滚查询。然后,您知道可以安全地还原您对产品表所做的所有更改。

永远不要截断该表,它是您的审计表。如果有人问你对产品目录做了什么,你可以回答任何问题,即使是5年后。

答案 1 :(得分:0)

这是一个单独的答案,说明如何将产品ID拆分为单独的部分 - 如果您必须更新产品ID的部分,我认为最好将其存储在单独的列中:

DECLARE @ProductRef TABLE
(ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, 
SrcNummer VARCHAR(255), DisplayNummer VARCHAR(255), SrcVater VARCHAR(255), DisplayVater VARCHAR(255), 
NummerSectionA VARCHAR(255), NummerSectionB VARCHAR(255), NummerSectionC VARCHAR(255), 
VaterSectionA VARCHAR(255), VaterSectionB VARCHAR(255), VaterSectionC VARCHAR(255) )
INSERT INTO @ProductRef (SrcNummer, SrcVater ) VALUES ('003.10TT032.1','003.10TT032.1')
INSERT INTO @ProductRef (SrcNummer, SrcVater ) VALUES ('003.10TT032.2L','003.10TT032.1')
INSERT INTO @ProductRef (SrcNummer, SrcVater ) VALUES ('003.10TT032.UY','003.10TT032.1')
DECLARE @Separator CHAR(1) 
SET @Separator = '.'

;WITH SeparatorPosition (ID, SrcNummer, NumFirstSeparator, NumSecondSeparator, SrcVater, VatFirstSeparator, VatSecondSeparator) 
AS (    SELECT 
        ID,
        SrcNummer, 
        CHARINDEX(@Separator,SrcNummer,0) AS NumFirstSeparator,
        CHARINDEX(@Separator,SrcNummer,  (CHARINDEX(@Separator,SrcNummer,0))+1  ) AS NumSecondSeparator,
        SrcVater, 
        CHARINDEX(@Separator,SrcVater,0) AS VatFirstSeparator,
        CHARINDEX(@Separator,SrcVater,  (CHARINDEX(@Separator,SrcVater,0))+1  ) AS VatSecondSeparator
    FROM @ProductRef )
UPDATE @ProductRef
SET 
    NummerSectionA = SUB.NummerSectionA , NummerSectionB = SUB.NummerSectionB , NummerSectionC = SUB.NummerSectionC ,
    VaterSectionA = SUB.VaterSectionA , VaterSectionB = SUB.VaterSectionB , VaterSectionC = SUB.VaterSectionC
FROM @ProductRef T
JOIN 
(
    SELECT  
        t.ID, 
        t.SrcNummer,
        SUBSTRING (t.SrcNummer,0,s.NumFirstSeparator) AS NummerSectionA,
        SUBSTRING (t.SrcNummer,s.NumFirstSeparator+1,(s.NumSecondSeparator-s.NumFirstSeparator-1) ) AS NummerSectionB,
        RIGHT (t.SrcNummer,(LEN(t.SrcNummer)-s.NumSecondSeparator)) AS NummerSectionC,
        t.SrcVater,
        SUBSTRING (t.SrcVater,0,s.NumFirstSeparator) AS VaterSectionA,
        SUBSTRING (t.SrcVater,s.NumFirstSeparator+1,(s.NumSecondSeparator-s.NumFirstSeparator-1) ) AS VaterSectionB,
        RIGHT (t.SrcVater,(LEN(t.SrcVater)-s.NumSecondSeparator)) AS VaterSectionC
    FROM @ProductRef t
    JOIN SeparatorPosition s
    ON t.ID = s.ID  
) SUB
ON T.ID = SUB.ID 

然后您只能使用正确的产品ID部分。

相关问题