我一直在忙着编写一个包含两个临时表和一个游标的存储过程。我收到这个作业已经两天了,这给了我一个艰难的时间,因为这是我第一次忙于编写这样的SP复杂性。
光标应该从DATABASE_X派生数据,并允许获取数据以与DATABASE_Y进行比较。
DATABASE_Y 中的 TableInfo 表包含 DATABASE_X 中的所有或大多数模式和表。类似的事情也适用于 ColumnInfo 表,唯一的区别是 TableInfo 表也能够包含列数据。
临时表分别包含 DATABASE_Y.TableInfo 中不存在的表的数据和 DATABASE_Y.ColumnInfo 中不存在的列的数据比较后填写。 (不存在意味着表A存在于DBX中但不存在于DBY.TableInfo的行中,反之亦然,对于列的情况而言)
DATABASE_Y.TableInfo中存在的 NotInUse 列是决定是否应该考虑DBX中的表的决定因素。
CREATE TABLE #NONEXISTENT_TABLES(
SCHEMA_NAME VARCHAR(100),
TABLE_NAME VARCHAR(100)
)
CREATE TABLE #NONEXISTENT_COLUMNS(
SCHEMA_NAME VARCHAR(100),
TABLE_NAME VARCHAR(100),
COLUMN_NAME VARCHAR(100)
)
DECLARE @SchemaName VARCHAR(100)
DECLARE @TableName VARCHAR(100)
DECLARE @ColumnName VARCHAR(100)
USE DATABASE_X;
DECLARE CRS_GET_NONEXISTENT_STUFF CURSOR FOR
select s.name as 'sname', t.name as 'tname', c.name as 'cname'
from sys.schemas (nolock) s
join sys.tables (nolock) t
on s.schema_id = t.schema_id
join sys.columns (nolock) c
on c.object_id = t.object_id
order by 1,2,3
OPEN CRS_GET_NONEXISTENT_STUFF
FETCH NEXT FROM CRS_GET_NONEXISTENT_STUFF INTO @SchemaName,
@TableName,
@ColumnName
WHILE @@FETCH_STATUS = 0
BEGIN
select @SchemaName, @TableName
from DATABASE_Y..TableInfo (nolock) ti
print @SchemaName + '-' + @TableName
IF @@ROWCOUNT = 1
BEGIN
declare @NotInUse varchar(100)
select @NotInUse = ti.[NotInUse]
from DATABASE_Y..TableInfo (nolock) ti
where ti.[Schema] = @SchemaName
and ti.[Name] = @TableName
print @SchemaName + '-' + @TableName
IF @NotInUse = '0'
DECLARE @colname varchar(100)
BEGIN
select @colname = ci.[Name]
from DATABASE_Y..ColumnInfo (nolock) ci
where ci.[TableSchema] = @SchemaName
and ci.[TableName] = @TableName
and ci.[Name] = @ColumnName
print @SchemaName + '-' + @TableName + '-' + @ColumnName
IF @colname IS NULL
BEGIN
INSERT INTO #NONEXISTENT_COLUMNS(SEMA_ADI, TABLO_ADI, KOLON_ADI)
VALUES(@SchemaName, @TableName, @colname)
END
END
END
ELSE
INSERT INTO #NONEXISTENT_TABLES(SCHEMA_NAME, TABLE_NAME)
VALUES (@SchemaName, @TableName)
FETCH NEXT FROM CRS_GET_NONEXISTENT_STUFF INTO @SchemaName,
@TableName,
@ColumnName
END
CLOSE CRS_GET_NONEXISTENT_STUFF
DEALLOCATE CRS_GET_NONEXISTENT_STUFF
SELECT * FROM #NONEXISTENT_COLUMNS
SELECT * FROM #NONEXISTENT_TABLES
DROP TABLE #NONEXISTENT_COLUMNS
DROP TABLE #NONEXISTENT_TABLES
假设: * DBX上的第一个模式是AAA,而AAA的DBX上的第一个表是BBBBB * AAA的第二个表是CCCCC;
我收到了无数数量的表,因为它看起来几乎不像是快速查询,只有AAA-BBBBB显示在5-6个表中,大约有5000行,然后转到AAA -CCCCC做了上面发生的事情,并且一直在继续。
我认为我的错误是将SELECT命令放在WHILE循环下,但我也相信这不是我唯一的错误......
我很高兴收到你们所有人对这个问题的建议。
我为单纯的文字墙道歉。
答案 0 :(得分:1)
我建议的第一件事是阅读这篇文章 - Bad habits : Putting NOLOCK everywhere。
接下来就是为每个循环运行一次:
select @SchemaName, @TableName
from DATABASE_Y..TableInfo (nolock) ti;
print @SchemaName + '-' + @TableName;
IF @@ROWCOUNT = 1
....
为了清晰起见,我添加了换行符和语句终止符,但第一个选择是为什么要获得大量结果集。这没有任何作用,将为数据库中的每一列运行。此外,如果你有IF @@ROWCOUNT = 1
,它将始终返回0,因为它遵循打印命令,该命令不返回任何行。所以你永远不会进入" true"此IF/ELSE
块的部分。
我很确定你根本不需要光标,作为一般规则,除非你绝对必须使用光标,否则你不应该使用光标。所以我认为你可以简单地用两个基于集合的插入替换所有循环:
CREATE TABLE #NONEXISTENT_TABLES(
SCHEMA_NAME VARCHAR(100),
TABLE_NAME VARCHAR(100),
object_id INT NOT NULL
);
CREATE TABLE #NONEXISTENT_COLUMNS(
SCHEMA_NAME VARCHAR(100),
TABLE_NAME VARCHAR(100),
COLUMN_NAME VARCHAR(100)
);
INSERT #NONEXISTENT_TABLES (SCHEMA_NAME, TABLE_NAME, objecobject_idt_ID)
SELECT s.name, t.Name, object_id
FROM sys.tables AS t
INNER JOIN sys.schemas AS s
ON s.schema_id = t.schema_id
WHERE NOT EXISTS
( SELECT 1
FROM DATABASE_Y..TableInfo AS ti
WHERE ti.TableSchema = s.Name
AND ti.name = t.name
--AND ti.NotInUse = 0
);
INSERT #NONEXISTENT_COLUMNS (SCHEMA_NAME, TABLE_NAME, COLUMN_NAME)
SELECT nt.SCHEMA_NAME, nt.TABLE_NAME, c.name
FROM sys.columns AS c
INNER JOIN #NONEXISTENT_TABLES AS nt
ON nt.object_id = c.object_id);