我写了一段代码,将列添加到名为 dbo.Master_Table 的表中。 该表包含当前数据库中存在的所有列。 使用了两个游标,第一个游标( TABLE_NAME )为我提供了所有游标的列表 数据库中的表,第二个光标( COLUMNS_TO_ADD )是 在(TABLE_NAME)中声明,它使我获得所有列的列表 在数据库中。
错误:
每个表中的列名必须唯一。列名称“ 解决方案” 在表'dbo.Master_table'中指定了多次。
信息2705,第16级,州4,第5行 每个表中的列名必须唯一。栏名 表'dbo.Master_table'中的'Sample_Size'指定为 一次
列'Resolution'和'Sample_Size'是最后一列 ORDINAL_POSITION 在各自的表格中。看起来像最后一个 迭代游标无法中断循环并尝试插入 他们的专栏再次。任何帮助将不胜感激。
/* Declaring the variables */
CREATE PROCEDURE DBO.SP_INSERT_MASTER
@TABLE_NAME VARCHAR(max)=NULL,
@COLUMN_NAME VARCHAR(20)=NULL,
@DATA_TYPE VARCHAR(20)=NULL,
@LENGTH INT=NULL,
@NUMERIC_PRECISION INT=NULL,
@NUMERIC_SCALE INT=NULL,
@ORDINAL_POSITION INT=NULL,
@Column varchar(max)=NULL,
@SQL varchar(max)=NULL
AS
SET NOCOUNT ON;
/* Declaring a cursor to fetch the number of tables in the DB */
DECLARE TABLE_NAME_1 CURSOR FOR
select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME NOT
IN('Master','Sysssislog','XML_DB')
OPEN TABLE_NAME_1
FETCH NEXT FROM TABLE_NAME_1
INTO @TABLE_NAME
WHILE @@FETCH_STATUS=0
--1
BEGIN
/* Declaring a cursor to get all the columns with their
length,precision,scale,ordinal position */
DECLARE COLUMN_TO_ADD CURSOR FOR
SELECT COLUMN_NAME,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,
NUMERIC_SCALE,ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME LIKE '%' + @TABLE_NAME + '%'
OPEN COLUMN_TO_ADD
/* Creating Temporary table to check redundant records */
----------------------------------------------------------------------
IF EXISTS (
SELECT * FROM tempdb.sys.objects WHERE name LIKE'%#Temp2%'
)
--2
BEGIN
DROP TABLE #TEMP2
--2
END;
select MAX(I.ORDINAL_POSITION) AS ORDINAL,I.TABLE_NAME INTO #TEMP2 from
INFORMATION_SCHEMA.COLUMNS I
INNER JOIN INFORMATION_SCHEMA.COLUMNS I2
ON I.TABLE_NAME=I2.TABLE_NAME
WHERE I.TABLE_NAME NOT IN( 'Master','Sysssislog','XML_DB') group by
I.TABLE_NAME
-----------------------------------------------------------------------
FETCH NEXT FROM COLUMN_TO_ADD
INTO @COLUMN_NAME,@DATA_TYPE,@LENGTH,@NUMERIC_PRECISION,@NUMERIC_SCALE,
@ORDINAL_POSITION
WHILE @@FETCH_STATUS=0
--3
BEGIN
IF @DATA_TYPE IN ('int','tinyint','bigint')
SET @Column = (@COLUMN_NAME +' '+ @DATA_TYPE + ' '+ '' )
IF @DATA_TYPE IN ('varchar','nvarchar')
SET @Column = (@COLUMN_NAME +' '+ @DATA_TYPE + ' '+ '('+
CAST(CASE(isnull(@LENGTH,'')) WHEN -1 THEN 1000 ELSE (isnull(@LENGTH,''))
END AS varchar(max)) +')'+ '' )
IF @DATA_TYPE IN ('decimal','numeric')
SET @Column = (@COLUMN_NAME +' '+ @DATA_TYPE + ' '+ '('+
cast(@NUMERIC_PRECISION as varchar(max))+','+cast(@NUMERIC_SCALE as
varchar(max))+')' + '' )
/*
ADD New Columns TO Master Table
*/
IF NOT EXISTS
(
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME LIKE '%Master_table%'
and COLUMN_NAME=@COLUMN_NAME
)
--4
BEGIN
Set @SQL='ALTER TABLE dbo.Master_table ADD'+ ' ' + (@Column)
EXEC(@SQL)
--PRINT @TABLE_NAME
--PRINT 'Y'
--PRINT @Column
FETCH NEXT FROM COLUMN_TO_ADD
INTO @COLUMN_NAME,@DATA_TYPE,@LENGTH,@NUMERIC_PRECISION,
@NUMERIC_SCALE,@ORDINAL_POSITION
--4
END;
ELSE
IF EXISTS
(
select 1 from #TEMP2
WHERE @TABLE_NAME=TABLE_NAME and ORDINAL=@ORDINAL_POSITION
)
--5
BEGIN
PRINT @TABLE_NAME
FETCH NEXT FROM TABLE_NAME_1
INTO @TABLE_NAME
--PRINT @TABLE_NAME
--PRINT 'N'
--PRINT @Column
--5
END;
FETCH NEXT FROM COLUMN_TO_ADD
INTO @COLUMN_NAME,@DATA_TYPE,@LENGTH,@NUMERIC_PRECISION,
@NUMERIC_SCALE,@ORDINAL_POSITION
--3
END;
FETCH NEXT FROM TABLE_NAME_1
INTO @TABLE_NAME
--drop #temp1
CLOSE COLUMN_TO_ADD;
DEALLOCATE COLUMN_TO_ADD;
--1
END;
CLOSE TABLE_NAME_1;
DEALLOCATE TABLE_NAME_1;
答案 0 :(得分:0)
似乎我的查询已解决。我只是意识到我在第一个TABLE_NAME_1游标的where子句中缺少完整的表名。 (使用“ Master”代替Master_Table)。我想这就是T-sql查询试图将数据再次从dbo.Master_Table插入同一张表的原因。 进行更改后,我的查询顺利通过。感谢您的帮助。
答案 1 :(得分:0)
您对代码的一些评论:
object_id
,可用于加入视图。无论如何,您不需要2个游标。#TEMP2
,将表的每一列与每一列相连。您仅访问联接的一侧,因此没有必要。另外,脚本只应创建该表一次(您可以在外部WHILE循环中创建该表)。COLUMN_TO_ADD
游标将被提取两次(IF语句之后的第二次),而不检查@@FETCH_STATUS
,并且如果IF语句的条件位于如果ELSE部分为true,则TABLE_NAME_1光标将移至下一条记录,而无需重新定义仍指向上一个表的列的内部光标。Master_table
本身。char
和nchar
怎么样?我不想重新编写您的所有代码,我将留给您,只是一个提示来处理所有(或至少 more )数据类型:
SET @Column = QUOTENAME(@COLUMN_NAME) + ' ' + @DATA_TYPE +
CASE
WHEN @DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar') THEN
'(' + CASE @LENGTH WHEN -1 THEN 'max' ELSE CAST(@LENGTH AS varchar(max)) END +')'
WHEN @DATA_TYPE IN ('decimal', 'numeric') THEN
'(' + CAST(@NUMERIC_PRECISION as varchar(max)) + ',' + CAST(@NUMERIC_SCALE as varchar(max))+')'
ELSE ''
END