如何在 SQL Server 中使用替换更新多个列?

发布于 2024-07-29 01:44:06 字数 354 浏览 8 评论 0原文

如何更新表中的不同列和行? 我想做一些类似于 替换字符串在 SQL Server 中

我想这样做,但该值存在于同一类型的多个列中。 这些值是员工表的外键 varchar。 每列代表一个任务,因此同一员工可能会被分配到记录中的多个任务,并且这些任务在记录之间会有所不同。 我怎样才能有效地做到这一点? 基本上是替换整个表中不同列的所有内容。

感谢您的任何帮助或建议。

干杯, ~ck 在圣地亚哥

How do I update different columns and rows across a table? I want to do something similiar to replace a string in SQL server

I want to do this but the value exists in multiple columns of the same type. The values are foreign keys varchars to an employee table. Each column represents a task, so the same employee may be assigned to several tasks in a record and those tasks will vary between records. How can I do this effectively? Basically something of a replace all accross varying columns throughout a table.

Thanks for any help or advice.

Cheers,
~ck in San Diego

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

人心善变 2024-08-05 01:44:06

这应该可以解决问题:

UPDATE table1
SET field1 = replace(field1, 'oldstring', 'newstring'),
    field2 = replace(field2, 'oldstring2', 'newstring2')

等等...

This should do the trick:

UPDATE table1
SET field1 = replace(field1, 'oldstring', 'newstring'),
    field2 = replace(field2, 'oldstring2', 'newstring2')

etc...

天煞孤星 2024-08-05 01:44:06

主要思想是创建一个SQL Update语句,无论表有多少个字段。 它是在 SQL Server 2012 上创建的,但我认为它也可以在 2008 上运行。

示例表:

CREATE TABLE SampleTable
(
    Field1 INT,
    Field2 VARCHAR(20),
    Field3 VARCHAR(20),
    Field4 VARCHAR(100),
    Field5 DATETIME,
    Field6 NVARCHAR(10)
);

仅获取 varchar 和 nvarchar 字段。 根据您的要求更改OLD_TEXTNEW_TEXT。 如果您不仅需要匹配 varchar 和 nvarchar 字段,请更改 system_type_id 值。

SELECT 'UPDATE dbo.SampleTable SET ' + STUFF((SELECT ', [' + name + '] =   REPLACE([' + name + '], ''OLD_TEXT'', ''NEW_TEXT'')' 
FROM sys.COLUMNS
WHERE 
    [OBJECT_ID] = OBJECT_ID('SampleTable')
    AND [is_identity] = 0 --It's not identity field
    AND [system_type_id] in (167, 231) -- varchar, nvarchar
FOR XML PATH('')), 1,1, '')

最后一次查询的结果是:

UPDATE dbo.SampleTable SET  
    [Field2] = REPLACE([Field2], 'OLD_TEXT', 'NEW_TEXT'), 
    [Field3] = REPLACE([Field3], 'OLD_TEXT', 'NEW_TEXT'), 
    [Field4] = REPLACE([Field4], 'OLD_TEXT', 'NEW_TEXT'), 
    [Field6] = REPLACE([Field6], 'OLD_TEXT', 'NEW_TEXT');

只需复制结果并在SSMS中执行即可。 这个片段可以为您在编写更新语句时节省一些时间。

希望能帮助到你。

The main idea is to create a SQL Update sentence, no matter how many fields has the table. It was created on SQL Server 2012, however I think it works on 2008 too.

Sample table:

CREATE TABLE SampleTable
(
    Field1 INT,
    Field2 VARCHAR(20),
    Field3 VARCHAR(20),
    Field4 VARCHAR(100),
    Field5 DATETIME,
    Field6 NVARCHAR(10)
);

Get only varchar and nvarchar fields. Change OLD_TEXT and NEW_TEXT accord to your requirement. Change system_type_id values if you need match not only varchar and nvarchar fields.

SELECT 'UPDATE dbo.SampleTable SET ' + STUFF((SELECT ', [' + name + '] =   REPLACE([' + name + '], ''OLD_TEXT'', ''NEW_TEXT'')' 
FROM sys.COLUMNS
WHERE 
    [OBJECT_ID] = OBJECT_ID('SampleTable')
    AND [is_identity] = 0 --It's not identity field
    AND [system_type_id] in (167, 231) -- varchar, nvarchar
FOR XML PATH('')), 1,1, '')

The result of the last query is:

UPDATE dbo.SampleTable SET  
    [Field2] = REPLACE([Field2], 'OLD_TEXT', 'NEW_TEXT'), 
    [Field3] = REPLACE([Field3], 'OLD_TEXT', 'NEW_TEXT'), 
    [Field4] = REPLACE([Field4], 'OLD_TEXT', 'NEW_TEXT'), 
    [Field6] = REPLACE([Field6], 'OLD_TEXT', 'NEW_TEXT');

just copy the result and execute in SSMS. This snippet saves you a little time when writing the update sentence.

Hope it helps.

最偏执的依靠 2024-08-05 01:44:06

回答发帖者关于如何标准化此数据结构的补充问题。 这样做的方法如下:

Project
-------
ProjectID
ProjectName
etc...

Employee
--------
EmployeeID
EmployeeName
etc...

Task
----
TaskID
ProjectID
EmployeeID
TaskDescription
etc...

您当前的结构(项目表中有一堆 Task1、Task2 等...列)显然不是由了解关系数据库的人设计的。

在解雇该人的过程中,您可能会解释说他的设计违反了第一范式,同时将他定向到该链接文章的“跨列重复组”部分。

In answer to the poster's supplementary question about how to normalize this data structure. Here's how you'd do it:

Project
-------
ProjectID
ProjectName
etc...

Employee
--------
EmployeeID
EmployeeName
etc...

Task
----
TaskID
ProjectID
EmployeeID
TaskDescription
etc...

Your current structure, where you have a bunch of Task1, Task2, etc... columns in the Project table, was clearly not designed by somebody that understands relational databases.

During the process of firing that individual, you might explain that his design violates the First Normal Form, while directing him to the "Repeating groups across columns" section of that linked article.

世态炎凉 2024-08-05 01:44:06

我知道已经过去 12 年了,但我最近有一个类似的需求,这就是我解决它的方法(在没有运气在任何地方找到合适的完整解决方案之后)。 不同之处在于,我必须更改包含特定字符串值的所有数据库表中的值。 以下过程更为通用,也可用于一张表。

CREATE OR ALTER PROCEDURE UPDATE_ALL_COLUMNS
    @TableNameSearchFilter NVARCHAR(100),
    @TableSchema NVARCHAR(100),
    @TestValue NVARCHAR(100),
    @NewValue NVARCHAR(100)
AS
BEGIN
    
    DECLARE @NRCOLUMNS INT;
    DECLARE @i INT = 0;
    DECLARE @COLUMN NVARCHAR(100) = '';
    DECLARE @SQL NVARCHAR(MAX) = '';
    DECLARE @TableToUpdate NVARCHAR(256) = '';
    DECLARE @insertingNULL BIT;

    IF (@NewValue IS NULL) SET @insertingNULL = 1
    ELSE SET @insertingNULL = 0;

    WHILE @TableToUpdate IS NOT NULL
    BEGIN
        SELECT @TableToUpdate = MIN(TABLE_NAME)
        FROM INFORMATION_SCHEMA.TABLES
        WHERE TABLE_NAME LIKE @TableNameSearchFilter
            AND TABLE_SCHEMA = @TableSchema
            AND TABLE_NAME > @TableToUpdate;
            
        WITH CTE1 AS
        (
            SELECT ROW_NUMBER() OVER (ORDER BY ORDINAL_POSITION) AS RN
            FROM INFORMATION_SCHEMA.COLUMNS
            WHERE TABLE_NAME = @TableToUpdate
                AND TABLE_SCHEMA = @TableSchema                     
                AND (@insertingNULL = 0 OR (@insertingNULL = 1 AND IS_NULLABLE = 'YES'))
        )
        SELECT @i = MIN(RN), @NRCOLUMNS = MAX(RN) FROM CTE1;

        WHILE (@i <= @NRCOLUMNS AND @TableToUpdate IS NOT NULL)
        BEGIN
            WITH CTE AS
            (
                SELECT *, ROW_NUMBER() OVER (ORDER BY ORDINAL_POSITION) AS RN
                FROM INFORMATION_SCHEMA.COLUMNS
                WHERE TABLE_NAME = @TableToUpdate
                    AND TABLE_SCHEMA = @TableSchema                     
                    AND (@insertingNULL = 0 OR (@insertingNULL = 1 AND IS_NULLABLE = 'YES'))
            )
            SELECT @COLUMN = COLUMN_NAME 
            FROM CTE
            WHERE RN = @i;

            SET @SQL = @SQL + 
                N'UPDATE D SET ' + @COLUMN + N' = ' + ISNULL(N'''' + @NewValue + N'''', N'NULL')
                + N' FROM ' + @TableSchema + N'.' + @TableToUpdate + N' D WHERE CAST(D.' + @COLUMN + ' AS NVARCHAR) = ' + ISNULL(N'''' + @TestValue + N'''', N'NULL') + ';'
                + NCHAR(13) + NCHAR(10);

            SET @i = @i + 1;
        END;        
    END;    

    --PRINT SUBSTRING(@SQL, 1, 4000)
    --PRINT SUBSTRING(@SQL, 4001, 8000)
    --PRINT SUBSTRING(@SQL, 8001, 12000)
    --PRINT SUBSTRING(@SQL, 12001, 16000)
    --PRINT SUBSTRING(@SQL, 16001, 20000)
    --PRINT SUBSTRING(@SQL, 20001, 24000)
    EXEC (@SQL)
END
GO

作为使用示例:

EXEC UPDATE_ALL_COLUMNS '%temp%', 'dbo', '', NULL

参数:

  • @TableNameSearchFilter - 这将与 LIKE 运算符一起使用,以查找数据库中名称与该值匹配的所有表;
  • @TableSchema - 表的架构(通常是 dbo)
  • @TestValue - 在每个找到的表的所有列(和行)中搜索的值;
  • @NewValue - 用于替换 @TestValue 的值。 也可以为 NULL

说明:

  • EXEC 语句将在数据库的“dbo”模式上查找名称包含单词“temp”的所有表,然后在所有找到的表的所有列中搜索值“”(空字符串),然后用 NULL 替换该值。
  • 显然,如果您有很长的列/表名称或更新值,请确保更新参数的限制。
  • 确保首先注释最后一行 (EXEC (@SQL)) 并使用 PRINT 取消注释这些行,只是为了了解该过程的作用以及最终语句的外观。
  • 如果您想搜索NULL 值(即让@TestValue 为NULL),这不会工作(很可能)。 不过,也可以轻松更改它来实现此目的,方法是用 IS NULL 替换 WHERE 子句(在动态查询中)中的等号,并删除其余的当 @TestValue IS NULL 时,该行。
  • 该过程会插入 NULL 值,并且只会在 NULLABLE 列中执行此操作。

希望这最终能帮助某人。

I know it has been 12 years, but I recently had a similar requirement and this is how I solved it (after having no luck in finding a proper full solution anywhere). The difference was that I had to change the values in ALL of the database tables that contained a certain string value. The following procedure is more general, and can be used for one table too.

CREATE OR ALTER PROCEDURE UPDATE_ALL_COLUMNS
    @TableNameSearchFilter NVARCHAR(100),
    @TableSchema NVARCHAR(100),
    @TestValue NVARCHAR(100),
    @NewValue NVARCHAR(100)
AS
BEGIN
    
    DECLARE @NRCOLUMNS INT;
    DECLARE @i INT = 0;
    DECLARE @COLUMN NVARCHAR(100) = '';
    DECLARE @SQL NVARCHAR(MAX) = '';
    DECLARE @TableToUpdate NVARCHAR(256) = '';
    DECLARE @insertingNULL BIT;

    IF (@NewValue IS NULL) SET @insertingNULL = 1
    ELSE SET @insertingNULL = 0;

    WHILE @TableToUpdate IS NOT NULL
    BEGIN
        SELECT @TableToUpdate = MIN(TABLE_NAME)
        FROM INFORMATION_SCHEMA.TABLES
        WHERE TABLE_NAME LIKE @TableNameSearchFilter
            AND TABLE_SCHEMA = @TableSchema
            AND TABLE_NAME > @TableToUpdate;
            
        WITH CTE1 AS
        (
            SELECT ROW_NUMBER() OVER (ORDER BY ORDINAL_POSITION) AS RN
            FROM INFORMATION_SCHEMA.COLUMNS
            WHERE TABLE_NAME = @TableToUpdate
                AND TABLE_SCHEMA = @TableSchema                     
                AND (@insertingNULL = 0 OR (@insertingNULL = 1 AND IS_NULLABLE = 'YES'))
        )
        SELECT @i = MIN(RN), @NRCOLUMNS = MAX(RN) FROM CTE1;

        WHILE (@i <= @NRCOLUMNS AND @TableToUpdate IS NOT NULL)
        BEGIN
            WITH CTE AS
            (
                SELECT *, ROW_NUMBER() OVER (ORDER BY ORDINAL_POSITION) AS RN
                FROM INFORMATION_SCHEMA.COLUMNS
                WHERE TABLE_NAME = @TableToUpdate
                    AND TABLE_SCHEMA = @TableSchema                     
                    AND (@insertingNULL = 0 OR (@insertingNULL = 1 AND IS_NULLABLE = 'YES'))
            )
            SELECT @COLUMN = COLUMN_NAME 
            FROM CTE
            WHERE RN = @i;

            SET @SQL = @SQL + 
                N'UPDATE D SET ' + @COLUMN + N' = ' + ISNULL(N'''' + @NewValue + N'''', N'NULL')
                + N' FROM ' + @TableSchema + N'.' + @TableToUpdate + N' D WHERE CAST(D.' + @COLUMN + ' AS NVARCHAR) = ' + ISNULL(N'''' + @TestValue + N'''', N'NULL') + ';'
                + NCHAR(13) + NCHAR(10);

            SET @i = @i + 1;
        END;        
    END;    

    --PRINT SUBSTRING(@SQL, 1, 4000)
    --PRINT SUBSTRING(@SQL, 4001, 8000)
    --PRINT SUBSTRING(@SQL, 8001, 12000)
    --PRINT SUBSTRING(@SQL, 12001, 16000)
    --PRINT SUBSTRING(@SQL, 16001, 20000)
    --PRINT SUBSTRING(@SQL, 20001, 24000)
    EXEC (@SQL)
END
GO

As a usage example:

EXEC UPDATE_ALL_COLUMNS '%temp%', 'dbo', '', NULL

Parameters:

  • @TableNameSearchFilter - this will be used with the LIKE operator to find all the tables from your database whose names that match this value;
  • @TableSchema - the schema of the table (usually dbo)
  • @TestValue - the value to search for in ALL of the columns (and rows) of each found table;
  • @NewValue - the value to replace @TestValue with. Can also be NULL.

Explanation:

  • The EXEC statement will find ALL tables whose names contain the word 'temp', on the 'dbo' schema of your database, then search for the value '' (empty string) in ALL columns of ALL of the found tables, then replace this value with a NULL.
  • Obviously, if you have long(er) column/table names or the update value, make sure to update the limits on the parameters.
  • Make sure to first comment the last line (EXEC (@SQL)) and uncomment the lines with PRINT, just to get an idea for what the procedure does and how the final statements look like.
  • This is not going to work (most likely) if you want to search for the NULL value (i.e. to have @TestValue as NULL). Nevertheless, it can be easily changed to accomplish this as well, by replacing the equal sign from the WHERE clause (in the dynamic query) with IS NULL and removing the rest of the line, when @TestValue IS NULL.
  • The procedure accounts for inserting NULL values, and will only do so in NULLABLE columns.

Hope this helps someone eventually.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文