两个表作为用户定义函数的参数

Posted

技术标签:

【中文标题】两个表作为用户定义函数的参数【英文标题】:Two tables as parameters of user defined function 【发布时间】:2016-11-07 15:24:48 【问题描述】:

我正在尝试在 SQL SERVER 中创建一个函数,我可以使用它来比较两个表,以检查它们是否相同。我这样做有两个例外。

这些表应该是完全相同的,具有相同的数据格式和列名,以及两个表中的所有值都相同。这将是手动检查,因此如果存在差异,抛出的错误不是问题。目的只是看看创建表的两种方法是否会导致相同的表。

我对 SQL 中的函数真的很陌生,所以我不知道如何解决这个问题。 我想将这两个表作为参数传递给函数,以获得如下结果:

CREATE FUNCTION DIFFERING_ROWS
(@TABLE1, @TABLE2)
RETURNS TABLE

AS
RETURN (
    SELECT *, 'A_not_B' as [Difference] FROM @TABLE1
    except
    SELECT *, 'A_not_B' as [Difference] FROM @TABLE2
    union all
    SELECT *, 'B_not_A' as [Difference] FROM @TABLE2
    except
    SELECT *, 'B_not_A' as [Difference] FROM @TABLE1
    )
END

这是如何正确实施的? 有人可以帮帮我吗?

【问题讨论】:

这很容易出错。如果这两个表没有完全相同的列和数据类型,它将失败。当然,这首先取决于将其从函数中取出并放入动态 sql 中。 当然,除非您尝试使用表值参数,然后您可以在函数中执行此操作。但是您发布的代码没有数据类型,所以我们在这里猜测。 哦,是的,我会在问题中说明这一点。表应该是完全相同的,具有相同的数据格式和列名。这将是手动检查,因此如果存在差异,抛出的错误不是问题。 但是您传递的是表名还是表值参数?两张表的数据类型是什么? 好的。因此,然后更改为过程并将查询转换为动态 sql。确保使用 QUOTENAME 包装您的表名。当您在名称中包含空格等时,它会有所帮助,并且还将极大地帮助最大限度地降低 sql 注入的风险。 【参考方案1】:

您不能在函数中执行此操作。将表名作为参数传递的唯一方法是使用动态 SQL,而函数中不允许使用动态 SQL。您可以使用存储过程来做到这一点。

【讨论】:

那么这看起来像一个存储过程? 存储过程不使用 RETURN,而是使用动态 SQL 简单地执行 SELECT。【参考方案2】:

如果表具有相同的 column_names,您可以创建此存储过程:

CREATE PROCEDURE checkEqualTables
@table1 varchar(100),
@table2 varchar(100)
AS
BEGIN

DECLARE @xCount int;

(SELECT @xCount = COUNT(*) from (SELECT column_name FROM information_schema.COLUMNS WHERE table_name=@table1) base
         where column_name not in (SELECT column_name FROM information_schema.COLUMNS WHERE table_name=@table2))

IF(@xCount <= 0)    
    print 'Tables are equal!';
ELSE
    print 'Tables are not equal!'    

END

【讨论】:

我很确定 OP 对内容感兴趣,而不是实际的列。【参考方案3】:

好的,我从答案和 cmets 中获取了信息,并研究了如何将其放入程序中,这就是我构建的:

我认为这是我想要的:

CREATE PROCEDURE checkEqualTables
@table1 nvarchar(100),
@table2 nvarchar(100)
AS
BEGIN
    DECLARE @SQL nvarchar(max);

SET @SQL =  'SELECT * FROM '    + @TABLE1 +
            'except
            SELECT * FROM '     + @TABLE2 +
            'union all
            SELECT * FROM '     + @TABLE2 +
            'except
            SELECT * FROM '     + @TABLE1    
    EXECUTE sp_executesql @SQL

END

【讨论】:

以上是关于两个表作为用户定义函数的参数的主要内容,如果未能解决你的问题,请参考以下文章

如何在用户定义的函数中将数据库列作为参数传递?

是否可以在用户定义的函数中插入列作为参数?

如何制作一个以用户定义的表类型为参数并在sql中返回相同的函数?

使用用户定义函数作为临时表中的约束

函数如何将数组或设置值作为 PostgreSQL 中用户定义函数的参数 (IN)

使用用户定义函数作为表的 DB2 查询结构