删除多个表中的列,其列名与另一个表中的值类似

问题描述 投票:0回答:1

我需要帮助。我能够手动完成要求,但希望这可以自动化。请看下面。

  1. DB有很多表。
  2. 其中一个表'TblMaster'有2列。 一个。 CNAME 湾旗 样本表(TblMaster)创建代码:
    CREATE TABLE TblMaster (CName varchar(30), Flag int)
    INSERT INTO TblMaster (cname,flag) values ('ABC',0);
    INSERT INTO TblMaster (cname,flag) values ('DEF',1);
    INSERT INTO TblMaster (cname,flag) values ('GHI',1);
    INSERT INTO TblMaster (cname,flag) values ('JKL',1);
    INSERT INTO TblMaster (cname,flag) values ('MNO',1);
  1. 数据库中可能有其他几个表,其中有一个或多个列,其中包含来自表'TblMaster'的字符串内容'CName'。 样本表(TB1和TB2)创建代码:
   
    CREATE TABLE TB1 
    (
       ABC int ,
       ABC1 int, 
       ABC2 int,
       DEF varchar(30),
       DEF1 varchar(30),
       DEF2 varchar(30),
       GHI varchar(30),
       GHI1 varchar(30),
       JKL numeric,
       JKL1 numeric,
       MNO datetime,
       MNO1 datetime,
       NOTEXIST varchar(30),
       NOTEXIST1 varchar(30), 
       NOTEXIST2 varchar(30)  
    )

    INSERT INTO TB1 values (0,1,2,'d1','d2','d3','g1','g2',0.0,1.0,null,null,Null,NUll,Null)
    INSERT INTO TB1 values (0,1,2,'d1','d2','d3','g1','g2',0.0,1.0,null,null,Null,NUll,Null)
    INSERT INTO TB1 values (0,1,2,'d1','d2','d3','g1','g2',0.0,1.0,null,null,Null,NUll,Null)
    INSERT INTO TB1 values (0,1,2,'d1','d2','d3','g1','g2',0.0,1.0,null,null,Null,NUll,Null)


    CREATE TABLE TB2 
    (
       ABC int ,
       ABC1 int, 
       ABC2 int,
       DEF varchar(30),
       DEF1 varchar(30),
       DEF2 varchar(30),
       GHI varchar(30),
       GHI1 varchar(30),
       JKL numeric,
       JKL1 numeric,
       MNO datetime,
       MNO1 datetime,
       NOTEXIST varchar(30),
       NOTEXIST1 varchar(30), 
       NOTEXIST2 varchar(30)  
    )

    INSERT INTO TB2 values (0,1,2,'d1','d2','d3','g1','g2',0.0,1.0,null,null,Null,NUll,Null)
    INSERT INTO TB2 values (0,1,2,'d1','d2','d3','g1','g2',0.0,1.0,null,null,Null,NUll,Null)
    INSERT INTO TB2 values (0,1,2,'d1','d2','d3','g1','g2',0.0,1.0,null,null,Null,NUll,Null)
    INSERT INTO TB2 values (0,1,2,'d1','d2','d3','g1','g2',0.0,1.0,null,null,Null,NUll,Null)
  1. 要求:我想使用循环/变量在单次执行中自动执行以下手动步骤。我尝试定义一个变量,但它不起作用。 一个。从TblMaster中选择Flag = 1的CName值。 Select CName from TblMaster where FLAG = 1 This yields result: DEF GHI JKL MNO 湾使用上面4.a中的结果来识别DB中具有相似字符串内容(值)的其他表中的列名。下面的代码剪切选择'DEF'的值 SELECT t.name AS table_name,c.name AS column_name FROM sys.tables AS t INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID WHERE c.name LIKE '%DEF%' and t.name in ('TB1','TB2') ORDER BY table_name; This yields result: table_name column_name TB1 DEF TB1 DEF1 TB1 DEF2 TB2 DEF TB2 DEF1 TB2 DEF2 Similarly repeat the above for 'GHI', 'JKL', 'MNO'. C。删除步骤4.b中标识的表中的列(所有结果)。 ALTER TABLE TB1 DROP COLUMN DEF,DEF1,DEF2,GHI,GHI1,JKL, JKL1,MNO,MNO1 ALTER TABLE TB2 DROP COLUMN DEF,DEF1,DEF2,GHI,GHI1,JKL, JKL1,MNO,MNO1

提前致谢!!

以下是我尝试过的但是没有用。请帮忙。

DECLARE @cnt INT = 0 
DECLARE @tempcnt INT = 1
DECLARE @tempcname varchar(30)

/* Find the max number of count for which we need to check other tables */

SELECT @cnt = COUNT (*) FROM TblMaster WHERE flag = 1

/* Create a temporary table with Row Number and the Column that we need */

SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS id, CName 
INTO #TempTable
FROM (SELECT * FROM TblMaster WHERE flag = 1) t;

/* Loop through the temporary table to process each CName */

WHILE @tempcnt <= @cnt
BEGIN
  SELECT @tempcname = CName 
  FROM #TempTable WHERE id = @tempcnt     
  /* PRINT @tempcname */ 

/* Identify the Columns that have CName string as Column Name in other 
   tables */
ALTER TABLE TB1
DROP COLUMN 
(
SELECT c.name AS column_name
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE c.name LIKE %@tempcname% and t.name = TB1
)

ALTER TABLE TB2
DROP COLUMN 
(
SELECT c.name AS column_name
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE c.name LIKE %@tempcname% and t.name = TB2
)
SET @tempcnt = @tempcnt + 1;
END;

DROP TABLE #TempTable;
sql stored-procedures match
1个回答
0
投票

检查此过程是否按预期工作。

看看小提琴,(你会在底部找到一个链接)。

我使用了双动态查询。

第一个返回相似列的逗号分隔列表。

SELECT @columns = STUFF((SELECT ',' + COLUMN_NAME 
                      FROM INFORMATION_SCHEMA.COLUMNS
                      WHERE  (COLUMN_NAME LIKE '%DEF%' OR COLUMN_NAME LIKE '%GHI%' OR COLUMN_NAME LIKE '%JKL%' OR COLUMN_NAME LIKE '%MNO%') AND TABLE_NAME = 'TB1'
                      FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')

通过删除列来第二次查询alter table:

ALTER TABLE TB1 DROP COLUMN DEF,DEF1,DEF2,GHI,GHI1,JKL,JKL1,MNO,MNO1

这是功能:

CREATE PROCEDURE dbo.DropColumns(@table_name NVARCHAR(128))
AS
BEGIN

    DECLARE @cmd NVARCHAR(MAX);
    DECLARE @colsOR NVARCHAR(MAX);
    DECLARE @cols NVARCHAR(MAX);

    -- filter used in WHERE clause (COLUMN_NAME LIKE '%REF%' OR ...)
    SET @colsOR = STUFF((SELECT ' OR ' + CONCAT('COLUMN_NAME LIKE ''%', CName, '%''') 
                         FROM TblMaster
                         WHERE FLAG = 1
                         FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 4, '');

    -- columns returned separated by comma DEF,DEF1,DEF2,GHI,GHI1,JKL,JKL1,MNO,MNO1
    SET @cmd = 'SELECT @columns = STUFF((SELECT '','' + COLUMN_NAME 
                      FROM INFORMATION_SCHEMA.COLUMNS
                      WHERE  (' + @colsOR + ') AND TABLE_NAME = ''' + @table_name + '''
                      FOR XML PATH(''''), TYPE).value(''.'', ''NVARCHAR(MAX)''), 1, 1, '''')'

    EXEC sp_executesql @cmd, N'@columns NVARCHAR(MAX) OUTPUT', @columns = @cols OUTPUT;

    SET @cmd = 'ALTER TABLE ' + @table_name + ' DROP COLUMN ' + @cols;

    EXEC sp_executesql @cmd;

    RETURN 0;

END
GO
EXEC dbo.DropColumns @table_name = 'TB1';
GO
--check results
SELECT TABLE_NAME, COLUMN_NAME
FROM   INFORMATION_SCHEMA.COLUMNS
WHERE  TABLE_NAME = 'TB1';
GO
TABLE_NAME | COLUMN_NAME
:--------- | :----------
TB1        | ABC        
TB1        | ABC1       
TB1        | ABC2       
TB1        | NOTEXIST   
TB1        | NOTEXIST1  
TB1        | NOTEXIST2  

dbfiddle here

© www.soinside.com 2019 - 2024. All rights reserved.