Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SQL Server:检查子行是否存在_C#_Sql_Sql Server_Foreign Keys - Fatal编程技术网

C# SQL Server:检查子行是否存在

C# SQL Server:检查子行是否存在,c#,sql,sql-server,foreign-keys,C#,Sql,Sql Server,Foreign Keys,我正在开发一个web应用程序,其中有许多表,但两个表足以说明我的问题: 使用者 顺序 假设User表有一个主键UserID,它是Order表中名为CreatedBy_UserID的外键 在删除用户之前,我想检查订单表是否有即将删除的用户创建的记录 我知道,如果我试图删除该用户,就会发生SqlException,但我想事先检查Order表是否没有该用户创建的任何记录?是否有任何SQL代码,我可以运行它来检查一个表的所有外键,如果该行被引用 这对我来说通常是有用的代码,因为如果可以检测到用户存在于这

我正在开发一个web应用程序,其中有许多表,但两个表足以说明我的问题:

使用者 顺序 假设User表有一个主键UserID,它是Order表中名为CreatedBy_UserID的外键

在删除用户之前,我想检查订单表是否有即将删除的用户创建的记录

我知道,如果我试图删除该用户,就会发生SqlException,但我想事先检查Order表是否没有该用户创建的任何记录?是否有任何SQL代码,我可以运行它来检查一个表的所有外键,如果该行被引用

这对我来说通常是有用的代码,因为如果可以检测到用户存在于这些其他表中,我可以完全删除删除选项

我不想要一个简单的查询,从Order中选择COUNT*,其中CreatedBy_UserID==@UserID,因为如果我为Order表创建另一个外键,这将不起作用。相反,我想要的东西将遍历所有外键


可以这样做吗?

在存在多个FK列的情况下,没有干净的方法来迭代所有FK列。您必须构建一些动态SQL来查询系统表并依次测试每个表

就我个人而言,我不会这么做。我知道我有什么FKs:我将依次测试每个FKs

...
IF EXISTS (SELECT * FROM Order WHERE CreatedBy_UserID == @userID)
    RAISERROR ('User created Orders ', 16, 1)
IF EXISTS (SELECT * FROM Order WHERE PackedBy_UserID == @userID)
    RAISERROR ('User packed Orders', 16, 1)
...

您不会动态地遍历某个用户对象的每个属性,并对每个属性进行常规测试,是吗?每个属性都有代码

下面是我过去执行此任务时使用的sp的代码请原谅缩进:

create proc dbo.usp_ForeignKeyCheck(
@tableName varchar(100),
@columnName varchar(100),
@idValue int
) as begin


set nocount on

declare fksCursor cursor fast_forward for
select tc.table_name, ccu.column_name
from 
    information_schema.table_constraints tc join
    information_schema.constraint_column_usage ccu on tc.constraint_name = ccu.constraint_name join
    information_schema.referential_constraints rc on tc.constraint_name = rc.constraint_name join
    information_schema.table_constraints tc2 on rc.unique_constraint_name = tc2.constraint_name join
    information_schema.constraint_column_usage ccu2 on tc2.constraint_name = ccu2.constraint_name 
where tc.constraint_type = 'Foreign Key' and tc2.table_name = @tableName and ccu2.column_name = @columnName
order by tc.table_name

declare 
    @fkTableName varchar(100),
    @fkColumnName varchar(100),
    @fkFound bit,
    @params nvarchar(100),
    @sql nvarchar(500)

open fksCursor

fetch next from fksCursor
into @fkTableName, @fkColumnName

set @fkFound = 0
set @params=N'@fkFound bit output'

while @@fetch_status = 0 and coalesce(@fkFound,0) <> 1 begin

    select @sql = 'set @fkFound = (select top 1 1 from [' + @fkTableName + '] where [' + @fkColumnName + '] = ' + cast(@idValue as varchar(10)) + ')'
    print @sql
    exec sp_executesql @sql,@params,@fkFound output

    fetch next from fksCursor
    into @fkTableName, @fkColumnName

end

close fksCursor
deallocate fksCursor

select coalesce(@fkFound,0)

return 0
    end

此代码将为您提供为指定表定义的外键列表:

从sys.objects中选择不同的名称 其中,在sys.foreign\u key\u列中选择约束\u object\u id作为fk 其中fk.Parent\u object\u id=从sys.tables中选择object\u id
其中name='tablename'

您可以使用事务检查它。 我知道它看起来像石头斧头,但它工作得又快又稳

private bool TestUser(string connectionString, int userID)
{
    var result = true;

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();

        var command = connection.CreateCommand();
        var transaction = connection.BeginTransaction();

        command.Connection = connection;
        command.Transaction = transaction;

        try
        {
            command.CommandText = "DELETE User WHERE UserID = " + userID.ToString();
            command.ExecuteNonQuery();
            transaction.Rollback();
        }
        catch
        {
            result = false;
        }
    }

    return result;
}

要使用thisTrue,您应该知道所有具有外键的字段,尽管良好的db设计只能从父表的Id列中使用FK。从其他列中FK不是很好的实践。
private bool TestUser(string connectionString, int userID)
{
    var result = true;

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();

        var command = connection.CreateCommand();
        var transaction = connection.BeginTransaction();

        command.Connection = connection;
        command.Transaction = transaction;

        try
        {
            command.CommandText = "DELETE User WHERE UserID = " + userID.ToString();
            command.ExecuteNonQuery();
            transaction.Rollback();
        }
        catch
        {
            result = false;
        }
    }

    return result;
}