Sql server 查找在一个过程中外键中使用的任何特定值

Sql server 查找在一个过程中外键中使用的任何特定值,sql-server,sql-server-2008,tsql,Sql Server,Sql Server 2008,Tsql,下午好 我正在使用SQLServer2008/TSQL。可能需要注意的是,我没有对任何数据库的写访问权限(我是只读用户)。我没有对数据库的写入权限,但如果绝对需要,可以插入临时表 首先,我想让大家知道我没有接受过SQL方面的正规教育。希望这是有道理的-我可能在一些词汇等方面不准确 我正在尝试的范围: 1.从表中选择列(主键)中的特定recordID(值) 2.查找在所有从属项/外键中使用该特定编号/记录ID的位置 3.返回tablename和columnname,并计算找到该值的次数 所以,作为

下午好

我正在使用SQLServer2008/TSQL。可能需要注意的是,我没有对任何数据库的写访问权限(我是只读用户)。我没有对数据库的写入权限,但如果绝对需要,可以插入临时表

首先,我想让大家知道我没有接受过SQL方面的正规教育。希望这是有道理的-我可能在一些词汇等方面不准确

我正在尝试的范围: 1.从表中选择列(主键)中的特定recordID(值) 2.查找在所有从属项/外键中使用该特定编号/记录ID的位置 3.返回tablename和columnname,并计算找到该值的次数

所以,作为一个例子。。。 您有一个表,其中包含与recordID关联的人员的信息,例如: 带有记录ID、名称等的dbo.MemberInfo

成员的ID号(MemberInfo.RecordID)用于其他 表,例如:dbo.Awards作为[荣誉ID] (dbo.Awards.HonoreeID=MemberInfo.RecordID)dbo.Address为[MemberID] (dbo.Address.MemberID=MemberInfo.RecordID)dbo.Contact as[PersonID] (dbo.Contact.PersonID=MemberInfo.RecordID)…可能还有一些 百人

我基本上想浏览所有的表,看看某个特定的值/记录被使用了多少次。现在,为了增加一些复杂性,它需要是通用的,因为我可能正在查找依赖项的列可能每天都在变化。(例如,我明天可能要寻找EventID的家属)

我目前的程序是: -使用select查找所需人员的ID -查看所有链接到dbo.Members的RecordID(主键)的外键 -将外键的表名和列转储到Excel中 -使用WHERE=@变量查找并替换一组SELECT计数 -将其放入SQL,定义my变量并将其设置为初始ID号

一定有更好的办法。我尝试了以下多种方法,但都出现了很多错误,没有成功:

--DECLARE @Selected CHAR
SELECT T.Name, C.Name
--SET @Selected=(SELECT T.Name FROM sys.tables T)
--CASE WHEN (T.NAME IS NOT NULL) THEN 1
--ELSE '0' END AS 'MyTrial'
FROM 
--sys.tables t
sys.foreign_key_columns AS fk
INNER JOIN sys.tables AS t ON fk.parent_object_id = t.object_id
INNER JOIN sys.columns AS c ON fk.parent_object_id = c.object_id AND fk.parent_column_id = c.column_id
WHERE Referenced_Object_ID=--Insert object ID here
我的思路是: 1.查询表/列中使用的外键,从相关表返回表名和列名 2.将这些结果输入到可以构建新查询的内容中,以便在适用的情况下返回每个表/列中的值计数 3.还返回tablename,以便在我需要查看构成计数的详细信息时,可以轻松地将其输入到另一个select语句中

所以我的结果可能是这样的: Tablename、Columnname、列中的值计数

理想情况下,如果计数小于1,则不会返回任何值、表名等


我的过程可能在一开始就有极大的缺陷,但提供的任何东西都能帮助我学习。谢谢

下面的脚本不使用存储过程,但使用临时表。据我所知,这是没有办法的。它对我来说运行得非常快,尽管我使用的是一个相对较小的测试数据库

这是我第一次尝试使用动态SQL,所以我无法证明这段代码对SQL注入攻击之类的攻击是安全的。一、 我也是自学成才的

Declare @Primary_Table varchar(100) = '';
Declare @Column_Name varchar(100) = '';
Declare @Specific_Value int = ;

IF(OBJECT_ID('tempdb..#Selected_Tables') is not null)
Begin
    Drop Table #Selected_Tables;
End

Select Distinct T.Name as Table_Name
    , C.Name as Column_Name
    , CAST(null as bigint) as Referenced_Records

Into #Selected_Tables

FROM sys.foreign_key_columns AS fk
    INNER JOIN sys.tables AS t 
        ON fk.parent_object_id = t.object_id
    INNER JOIN sys.columns AS c 
        ON fk.parent_object_id = c.object_id 
            AND fk.parent_column_id = c.column_id
    Inner Join sys.tables AS t2 
        ON fk.referenced_object_id = t2.object_id
    Inner Join sys.columns AS c2 
        on fk.referenced_column_id = c2.column_id

Where t2.name = @Primary_Table
    and c2.Name = @Column_Name;

Declare @sqlCommand nvarchar(max);
Declare @Unprocessed_Records int = (Select Count(1) 
                                    From #Selected_Tables 
                                    Where Referenced_Records is null);
Declare @Processing_Table varchar(1000) = (Select Top 1 Table_Name
                                            From #Selected_Tables
                                            Where Referenced_Records is null);
Declare @Processing_Column varchar(1000) = (Select Top 1 Column_Name
                                            From #Selected_Tables
                                            Where Referenced_Records is null
                                                and Table_Name = @Processing_Table);

While @Unprocessed_Records > 0
Begin
    Set @sqlCommand = 'Update #Selected_Tables '
                        + 'Set Referenced_Records = (Select Count(1) '
                        + 'From ' + @Processing_Table + ' '
                        + 'Where ' + @Processing_Column + ' = ' + CAST(@Specific_Value as nvarchar(1000)) + ') '
                        + 'Where Table_Name = ''' + @Processing_Table + ''' '
                        + 'and Column_Name = ''' + @Processing_Column + ''';'

    Exec (@sqlCommand);

    Set @Unprocessed_Records = (Select Count(1) 
                                    From #Selected_Tables 
                                    Where Referenced_Records is null);
    Set @Processing_Table = (Select Top 1 Table_Name
                                            From #Selected_Tables
                                            Where Referenced_Records is null);
    Set @Processing_Column = (Select Top 1 Column_Name
                                            From #Selected_Tables
                                            Where Referenced_Records is null
                                                and Table_Name = @Processing_Table);
End;

Select * From #Selected_Tables;

下面的脚本不使用存储过程,但使用临时表。据我所知,这是没有办法的。它对我来说运行得非常快,尽管我使用的是一个相对较小的测试数据库

这是我第一次尝试使用动态SQL,所以我无法证明这段代码对SQL注入攻击之类的攻击是安全的。一、 我也是自学成才的

Declare @Primary_Table varchar(100) = '';
Declare @Column_Name varchar(100) = '';
Declare @Specific_Value int = ;

IF(OBJECT_ID('tempdb..#Selected_Tables') is not null)
Begin
    Drop Table #Selected_Tables;
End

Select Distinct T.Name as Table_Name
    , C.Name as Column_Name
    , CAST(null as bigint) as Referenced_Records

Into #Selected_Tables

FROM sys.foreign_key_columns AS fk
    INNER JOIN sys.tables AS t 
        ON fk.parent_object_id = t.object_id
    INNER JOIN sys.columns AS c 
        ON fk.parent_object_id = c.object_id 
            AND fk.parent_column_id = c.column_id
    Inner Join sys.tables AS t2 
        ON fk.referenced_object_id = t2.object_id
    Inner Join sys.columns AS c2 
        on fk.referenced_column_id = c2.column_id

Where t2.name = @Primary_Table
    and c2.Name = @Column_Name;

Declare @sqlCommand nvarchar(max);
Declare @Unprocessed_Records int = (Select Count(1) 
                                    From #Selected_Tables 
                                    Where Referenced_Records is null);
Declare @Processing_Table varchar(1000) = (Select Top 1 Table_Name
                                            From #Selected_Tables
                                            Where Referenced_Records is null);
Declare @Processing_Column varchar(1000) = (Select Top 1 Column_Name
                                            From #Selected_Tables
                                            Where Referenced_Records is null
                                                and Table_Name = @Processing_Table);

While @Unprocessed_Records > 0
Begin
    Set @sqlCommand = 'Update #Selected_Tables '
                        + 'Set Referenced_Records = (Select Count(1) '
                        + 'From ' + @Processing_Table + ' '
                        + 'Where ' + @Processing_Column + ' = ' + CAST(@Specific_Value as nvarchar(1000)) + ') '
                        + 'Where Table_Name = ''' + @Processing_Table + ''' '
                        + 'and Column_Name = ''' + @Processing_Column + ''';'

    Exec (@sqlCommand);

    Set @Unprocessed_Records = (Select Count(1) 
                                    From #Selected_Tables 
                                    Where Referenced_Records is null);
    Set @Processing_Table = (Select Top 1 Table_Name
                                            From #Selected_Tables
                                            Where Referenced_Records is null);
    Set @Processing_Column = (Select Top 1 Column_Name
                                            From #Selected_Tables
                                            Where Referenced_Records is null
                                                and Table_Name = @Processing_Table);
End;

Select * From #Selected_Tables;

看起来和这个项目很相似:查看器选择所有数据,你只需要计数。我最初的建议是暂时不要考虑让它通用化。设置一个变量并使用它成功地测试它。例如,如果我在AdventureWorks中使用462624691,我将获得Address/StateProvinceID和SalesTaxRate/StateProvinceID。因此,我必须问自己,这是否就是我正在寻找的数据。然后调整它直到我得到我想要的。这将有助于查看当前查询和过程的示例。看起来与此项目类似:查看器选择所有数据,您只需要计数。我最初的建议是暂时不要考虑将其设置为通用。设置一个变量并使用它成功地测试它。例如,如果我在AdventureWorks中使用462624691,我将获得Address/StateProvinceID和SalesTaxRate/StateProvinceID。因此,我必须问自己,这是否就是我正在寻找的数据。然后调整它直到我得到我想要的。查看当前查询和流程的示例会有所帮助。