0

我有一种情况需要删除字符“。” 来自特定表中具有唯一性约束的 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

4 回答 4

1

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

如果答案是“否”,那么只需放弃约束即可。

于 2013-11-11T22:26:06.093 回答
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 并使用 a 调用它cross apply)。

我将不得不更加努力地考虑如何使其基于工作集。当我睡了一会儿,我可能会带着不同的答案回来。

于 2013-11-12T00:53:46.833 回答
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
于 2013-11-12T16:55:04.323 回答
0

你可以这样做:

  1. 创建一个计数查询并在其中使用计数仅选择小于 2 的值
  2. 这个结果是没有重复的记录
  3. 使用此查询作为更新源
  4. 运行您的更新查询,这仅适用于没有重复的数据,并且更新将正确运行。

您可以创建另一个计数大于一个的查询来查找重复项并根据需要使用它们。

这是一个例子:

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
于 2013-11-11T22:37:05.833 回答