使用REPLACE替换唯一VARCHAR上的字符

时间:2013-11-11 22:21:58

标签: sql sql-server replace varchar unique-constraint

我有一种情况需要删除字符'。'来自VARCHAR在特定表中具有唯一性约束。我更喜欢在SQL上通过自定义应用程序代码执行此操作。我有改变的逻辑,但我正在努力克服如何克服VARCHAR的唯一性约束。

这是我的测试表:

CREATE TABLE [dbo].[TableName] (
    [TableNameID]   INT           IDENTITY (1, 1) NOT NULL,
    [TableInfo]     VARCHAR (128) NOT NULL,
    CONSTRAINT [unq_TableName] UNIQUE NONCLUSTERED ([TableInfo] ASC)
)

这是执行替换的逻辑(不处理唯一性约束):

UPDATE TableName
SET TableInfo = REPLACE(TableInfo, '.', '_')
WHERE TableInfo LIKE '%.%'

我正在尝试克服使用以下数据集创建的测试:

TableNameID | TableInfo
-------------------------
     1      |  Test
     2      |  Test.
     3      |  Test_
     4      |  Test__

对此的任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:1)

应该是独一无二的吗?如果答案是“是”,那么你必须以某种方式弄清楚如何去除数据的重复数据。在您的示例中,您如何处理ID 3?您将使用TableInfo ='Test_'创建两个记录。你必须开发一些组合或消除其中一种的方法。

如果答案为“否”,则只需删除约束。

答案 1 :(得分:0)

你可以这样做:

  1. 创建一个计数查询,并在其中使用count来仅选择小于2的值
  2. 此结果是没有重复的记录
  3. 使用此查询作为更新源
  4. 运行您的更新查询,这只适用于没有重复的数据,并且更新将正确运行。
  5. 您可以使用多个计数创建另一个查询以查找重复项,并根据需要使用它们。

    这是一个例子:

    UPDATE  TableToUpdate
    SET     columnToUpdate = REPLACE(columnToUpdate, '.', '')
    FROM    ( SELECT    COUNT(*) AS Count ,
                        ID
              FROM      TableToUpdate
              GROUP BY  columnToUpdate
              HAVING    ( COUNT(*) < 2 )
            ) AS QueryData
    WHERE   tableToUpdate.ID = QueryData.ID
    

答案 2 :(得分:0)

如果您知道要更新的行的PK,则此代码有效: -

declare @unique varchar(50)
set @unique = ''

while 1=1 begin
    set @unique+='_'
    update t set 
        t.TableInfo = replace(t.TableInfo, '.', @unique)
    from dbo.tablename t
    where t.TableNameID=2 --t.tableinfo like '%.%'
    and not exists(
        select *
        from dbo.TableName csq
        where csq.TableInfo = replace(t.TableInfo, '.', @unique)
    )
    if @@rowcount=1
        break
end

代码很脆弱,如果例如TableInfo列的宽度不足以通过附加多个下划线来创建唯一键,则会失败。

将光标枚举到需要更新的行的记录集上 - 然后为每个PK调用此代码应该是微不足道的(或将其转换为UDF并使用cross apply调用它)。

我必须更加努力地思考如何使其基于工作集。我睡觉时可能会回答不同的答案。

答案 3 :(得分:0)

谢谢胡安。你的帖子激励了我,让我思考计数。

我想出了以下内容(不像你的那样紧凑,但它有效)。我仍然需要处理“可能”长度问题,但我可以解决这个问题。

WHILE EXISTS (SELECT 1 FROM TableName WHERE TableInfo LIKE '%.%')
BEGIN
DECLARE @oldInfo VARCHAR(128)
SET @oldInfo = (SELECT TOP 1 TableInfo FROM TableName WHERE TableInfo LIKE '%.%')

DECLARE @newInfo VARCHAR(128)
SET @newInfo = REPLACE(@oldInfo, '.', '_')

DECLARE @count VARCHAR(128)
SET @count = (SELECT COUNT(*) FROM TableName WHERE TableInfo LIKE @newInfo + '%')

IF @count > 0
BEGIN
    IF (LENGTH(@newInfo) + LENGTH(@count) <= 128)
    BEGIN
        UPDATE TableName
        SET TableInfo = @newInfo + @count
        WHERE TableInfo = @oldInfo
    END
END
ELSE
BEGIN
    UPDATE TableName
    SET TableInfo = @newInfo
    WHERE TableInfo = @oldInfo
END
END