【发布时间】:2019-11-26 12:19:46
【问题描述】:
我正在尝试在 SQL 中编写一个函数,该函数应该返回一个表,该表是模式中所有表的联合。这可以在 SQL Server 中执行吗?
我经常需要在一个模式中连接表,为此我从这里找到了一个非常好的动态查询:
How to SELECT and UNION from a group of Tables in the schema in SQL Server 2008 R2
(MarkD的回答)
现在,因为我需要在不同的架构上重复执行此操作。我正在考虑编写一个函数,它将模式名称和通配符作为表名的输入,并输出所有表的联合。
但是,我担心在构造 create 函数时可能需要声明表列 - 我不能这样做,因为表应该是动态的!
我对 SQL 函数并不完全熟悉,我希望我可以像在 Python 中那样做这件事。这可能吗?
CREATE FUNCTION udfJoinTablesinSchema
(@Schemaname VARCHAR(100),
@TableNameWildcard VARCHAR(100))
RETURNS TABLE
AS
RETURN
(DECLARE @SelectClause VARCHAR(100) = 'SELECT *',
@Query NVARCHAR(MAX) = ''
SELECT @Query = @Query + @SelectClause + ' FROM ' + TABLE_SCHEMA+'.['+TABLE_NAME + '] UNION ALL '
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME like @TableNameWildcard
AND TABLE_SCHEMA = @Schemaname
SELECT @Query = LEFT(@Query, LEN(@Query) - LEN(' UNION ALL '))
PRINT(@Query)
EXEC(@Query)
);
我收到一条错误消息:
“DECLARE”附近的语法不正确。当我将鼠标悬停在 DECLARE 上时,期待 '('、SELECT 或 WITH。"。
它还抱怨两个标量变量@TableNameWildCard、@Schemaname。
【问题讨论】:
-
您不能在 SQL Server 的用户定义函数中使用动态 SQL。
-
@ZoharPeled 说了什么。但是您可以使用存储过程来做到这一点。
-
你应该使用
'...' + QUOTENAME(TABLE_NAME) + '...'而不是'...['+TABLE_NAME + ']...'。就像用于注入WHERE的字符串一样,用于注入对象的字符串也可能遭受注入攻击。 -
如果你的表在所有地方都具有相同的结构,我会说查找查询不是问题。多个相同的表非常清楚地表明设计是这里的真正问题。这种事情几乎总是使用一个额外的列来标识“类型”而不是几十个相同的表更好。
-
另外,错误的原因是因为您已将函数声明为内联表值函数,但将其编写为多行表值函数。后者的表现确实很差,但是,即使您可以在函数中使用动态 SQL,也不可能为此编写一个 tvf 作为内联的。幸运的是你不能,我想。
标签: sql sql-server function tsql dynamic