Sql 如何搜索主键ID';这些主键ID';s在列中具有相似的值

Sql 如何搜索主键ID';这些主键ID';s在列中具有相似的值,sql,database,reporting,analytics,Sql,Database,Reporting,Analytics,背景:我们正在研究为什么在一个过程中遗漏了许多账户。我们已经回到了我们所掌握的数据。我们现在有一个相当大的账户清单,无论出于何种原因,这些账户都被遗漏了。现在这个过程没有太多细节,非常复杂,我们需要知道为什么遗漏了这些账户,只有这些账户。就像任何数据库一样,我们有很多自动的过程一直在运行,所以现在真的不知道到底发生了什么导致这些帐户丢失。我认为解决这个问题的唯一办法是找出这些账户之间的相似之处。显然,我们已经尝试寻找更常见的地方,但后来什么也没有发现 问题:我想使用SQL返回数据库中的所有表名和

背景:我们正在研究为什么在一个过程中遗漏了许多账户。我们已经回到了我们所掌握的数据。我们现在有一个相当大的账户清单,无论出于何种原因,这些账户都被遗漏了。现在这个过程没有太多细节,非常复杂,我们需要知道为什么遗漏了这些账户,只有这些账户。就像任何数据库一样,我们有很多自动的过程一直在运行,所以现在真的不知道到底发生了什么导致这些帐户丢失。我认为解决这个问题的唯一办法是找出这些账户之间的相似之处。显然,我们已经尝试寻找更常见的地方,但后来什么也没有发现

问题:我想使用SQL返回数据库中的所有表名和列名,其中这些帐户列表在表的一列或多列中具有相同的值。我已经创建了一个查询来查找表名、列等,但不知道如何将它们组合在一起创建一个查询,以获得我想要的所有结果。我确信需要使用光标和大量内部连接,但我不确定该如何操作。
再一次: 假设我有账号123456和654321,我知道我们的数据库有3000个表,其中一列引用账号,名称为AccountNumber、AccountNum或account。我想搜索并查找所有表,这些表的列名称为AccountNumber、AccountNum或Account的值为123456或654321。然后对于这些表,对于每个表,我想获取列所在的行,无论名称是AccountNumber,AccountNum,或者Account的值为123456和654321,然后对于这些行中的每一行,我想检查每一行的每一列,看看账号123456行上的列是否与账号654321行上的列相等,如果是,那么我想让它返回列名和表名。通过这种方式,我可以看到这些账户的共同点

高级部分:

如果某个可怜的灵魂能够做到以上几点,那么我还想创建一个将返回的查询 表名及其更新时间。我将通过检查每个表中的每一列来获得更新的值,如果该列的类型为“timestamp”或默认值为“GetDate()”,则该列将被用作更新。在最终的结果集中,显示了它将订购的帐户编号的所有更改都已更新。

第一种方法,rustic(我不太习惯T-SQL,我做了更多的PL/SQL),但这可能会帮助您更进一步,并在SQL SERVER 2008中进行测试。希望它能在2005年起作用……)

因此,我们创建了两个过程,一个调用另一个

提供的代码只能检查一次 -对于2个不同的ID -对于所有相关字段(Account、AccountNum、AccountNumber)

想法(检查AccountNumber列)

查找表(在表信息_SCHEMA.columns中,其中列出了您的数据库表),这些表的列具有提供的3个名称之一

对于找到的每个表: 创建动态查询:

select count(*) from <THE_TABLE> where <Account_column_name> IN (123456 654321);
如果
count(*)=1
,则表示给定ID的同一表格的同一列中存在相同的值

在这种情况下,我们打印

要在sql management studio中启动搜索,只需

EXEC GetSimilarValuesForFieldAndValue  123456, 654321
在“消息”部分,您应该有一个“结果”列表

第二条:

CREATE procedure [dbo].[CompareFields](@TableName NVARCHAR(MAX), @FieldName NVARCHAR(MAX), @FirstId int, @SecondId int)  
as


DECLARE @ColumnName NVARCHAR(MAX)
DECLARE @Sql NVARCHAR(MAX)
DECLARE @Params NVARCHAR(MAX)
DECLARE @Count int


DECLARE cfCursor CURSOR FOR
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = ''+@TableName+' '
AND COLUMN_NAME <> ' '+@FieldName+''




OPEN cfCursor
  FETCH next from cfCursor into @ColumnName
  while @@FETCH_STATUS = 0

    begin
    select @Sql = 
    N' SELECT @Count = count(*) from ' +@TableName + ' T1 '+
    N' INNER JOIN ' + @TableName + ' T2 ON T1.' +@ColumnName + ' = T2.' + @ColumnName +
    N' WHERE T1.' +@FieldName + ' = '+ CAST(@FirstId as varchar) +
    N' AND T2.' + @FieldName + ' = '+CAST(@SecondId as varchar)
    SELECT @Params = 
    N'@TableName VARCHAR(MAX), @ColumnName VARCHAR(MAX), '+
    N'@FieldName VARCHAR(MAX), @FirstId int, @SecondId int, @Count int out'
    exec sp_executesql  @sql, @Params, @TableName, @ColumnName, @FieldName, @FirstId, @SecondId, @Count OUT
    if @Count = 1
    begin
    --print tableName and column Name if value is identic
     print 'Table : ' + @TableName + ' : same value for ' + @ColumnName
    end
    FETCH NEXT FROM cfCursor INTO @ColumnName    
    end
 close cfCursor

 DEALLOCATE cfCursor
GO
CREATE procedure[dbo].[CompareFields](@TableName-NVARCHAR(MAX)、@FieldName-NVARCHAR(MAX)、@FirstId-int、@SecondId-int)
作为
声明@ColumnName NVARCHAR(最大值)
声明@Sql NVARCHAR(最大值)
声明@Params NVARCHAR(最大值)
声明@countint
为其声明cfCursor游标
从INFORMATION\u SCHEMA.COLUMNS中选择COLUMN\u NAME
其中TABLE_NAME='+@TableName+''
和列名称“”+@FieldName+“”
开放式cfCursor
从cfCursor获取下一个到@ColumnName
而@@FETCH\u STATUS=0
开始
选择@Sql=
N'从'+@TableName+'T1'中选择@Count=Count(*)+
N'内部联接'+@TableName+'T2在T1上'+@ColumnName+'=T2'+@ColumnName'+
N'其中T1.'+@FieldName+'='+CAST(@FirstId作为varchar)+
N'和T2.'+@FieldName+'='+CAST(@SecondId作为varchar)
选择@Params=
N'@TableName VARCHAR(最大值),@ColumnName VARCHAR(最大值),'+
N'@FieldName VARCHAR(MAX),@FirstId int,@SecondId int,@Count int out'
exec sp_executesql@sql、@Params、@TableName、@ColumnName、@FieldName、@FirstId、@SecondId、@Count OUT
如果@Count=1
开始
--如果值相同,则打印表名和列名
打印“Table:”++@TableName+”:与“++@ColumnName”的值相同
结束
从cfCursor获取下一个到@ColumnName
结束
闭式cfCursor
解除分配cfCursor
去

实际上,我曾一度不得不为guid做这件事。下面是使用guid的脚本。一秒钟后,我将修改它以满足您的需要:

DECLARE @table VARCHAR(100)
DECLARE @column VARCHAR(100)
DECLARE @value INT

SET @value = '06B8BD6C-A8EC-4EB3-9562-6666EE86952D'

DECLARE table_cursor CURSOR
FOR select tbl.Name, cols.name as TableName  FROM sys.columns cols  JOIN 
    sys.tables tbl on cols.object_id = tbl.object_id
    where system_type_id = 36

OPEN table_cursor 
FETCH NEXT FROM table_cursor 
INTO @table, @column;

WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @SQL NVARCHAR(1000)

SET @SQL = 'SELECT ''' + @Table + '''  AS TBL,''' + 
@column + ''' AS COL FROM [' + @table + '] 
WITH(NOLOCK) WHERE ' + @column + ' = ''' + CAST(@value AS VARCHAR(50)) + ''''

    print @sql
EXEC sp_executesql @Sql

FETCH NEXT FROM table_cursor 
INTO @table, @column;

END

CLOSE table_cursor
DEALLOCATE table_cursor
更新为处理搜索字段名:

DECLARE @table VARCHAR(100)
DECLARE @column VARCHAR(100)
DECLARE @value UNIQUEIDENTIFIER

SET @value = --ENTER YOUR ACCOUNT NUMBER HERE

DECLARE table_cursor CURSOR

select tbl.Name, cols.name as TableName  FROM sys.columns cols  JOIN 
    sys.tables tbl on cols.object_id = tbl.object_id
    where cols.Name = 'AccountNumber' 
    OR cols.Name = 'AccountNum' OR cols.Name = 'Account'

OPEN table_cursor 
FETCH NEXT FROM table_cursor 
INTO @table, @column;

WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @SQL NVARCHAR(1000)

SET @SQL = 'SELECT ''' + @Table + '''  AS TBL,''' + @column + 
    ''' AS COL FROM [' + @table + '] WITH(NOLOCK) 
WHERE ' + @column + ' = ''' + CAST(@value AS VARCHAR(50)) + ''''
    print @sql
    EXEC sp_executesql @Sql

FETCH NEXT FROM table_cursor 
INTO @table, @column;

END

CLOSE table_cursor
DEALLOCATE table_cursor

如果这不够清楚,请随时询问更多细节。我会在早上7点左右再次查看这篇文章,看看是否有勇敢的灵魂尝试过这一壮举。sgbd会很好,因为这样的查询可以在系统表中进行;)知道你有一个GetDate可能还不够,这是什么数据库和版本?我会首先做什么(如果我在你那里,但我不是;):在你的数据库中创建这两个过程,并用很少的样本值测试它。这将帮助你了解你是否获得了太多的信息(我认为这会发生)。然后进行定制、重构、改进,等等。好吧,我想我已经找到了我认为应该采取的分析步骤。1.获取所有表的列表,这些表的列类型为int,其值等于账号an
DECLARE @table VARCHAR(100)
DECLARE @column VARCHAR(100)
DECLARE @value INT

SET @value = '06B8BD6C-A8EC-4EB3-9562-6666EE86952D'

DECLARE table_cursor CURSOR
FOR select tbl.Name, cols.name as TableName  FROM sys.columns cols  JOIN 
    sys.tables tbl on cols.object_id = tbl.object_id
    where system_type_id = 36

OPEN table_cursor 
FETCH NEXT FROM table_cursor 
INTO @table, @column;

WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @SQL NVARCHAR(1000)

SET @SQL = 'SELECT ''' + @Table + '''  AS TBL,''' + 
@column + ''' AS COL FROM [' + @table + '] 
WITH(NOLOCK) WHERE ' + @column + ' = ''' + CAST(@value AS VARCHAR(50)) + ''''

    print @sql
EXEC sp_executesql @Sql

FETCH NEXT FROM table_cursor 
INTO @table, @column;

END

CLOSE table_cursor
DEALLOCATE table_cursor
DECLARE @table VARCHAR(100)
DECLARE @column VARCHAR(100)
DECLARE @value UNIQUEIDENTIFIER

SET @value = --ENTER YOUR ACCOUNT NUMBER HERE

DECLARE table_cursor CURSOR

select tbl.Name, cols.name as TableName  FROM sys.columns cols  JOIN 
    sys.tables tbl on cols.object_id = tbl.object_id
    where cols.Name = 'AccountNumber' 
    OR cols.Name = 'AccountNum' OR cols.Name = 'Account'

OPEN table_cursor 
FETCH NEXT FROM table_cursor 
INTO @table, @column;

WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @SQL NVARCHAR(1000)

SET @SQL = 'SELECT ''' + @Table + '''  AS TBL,''' + @column + 
    ''' AS COL FROM [' + @table + '] WITH(NOLOCK) 
WHERE ' + @column + ' = ''' + CAST(@value AS VARCHAR(50)) + ''''
    print @sql
    EXEC sp_executesql @Sql

FETCH NEXT FROM table_cursor 
INTO @table, @column;

END

CLOSE table_cursor
DEALLOCATE table_cursor