【问题标题】:Table Valued Function with dynamic select statement具有动态选择语句的表值函数
【发布时间】:2019-11-05 05:27:55
【问题描述】:

创建一个用户定义的表值函数,该函数应返回 select union all 动态查询。

我有表 tbl_tablesinfo,其中包含表名 tbl1tbl2tbl3 等,共有大约 3000 个表名。

我不想创建视图,而是创建函数,它应该通过 union all 返回所有表 select * from

我的尝试:

CREATE FUNCTION udf_alldata()
RETURNS TABLE
AS
BEGIN
    DECLARE @Var VARCHAR(MAX) = ''

    SELECT 
        @Var = STUFF((SELECT ' SELECT * FROM [' + tbl.TableNames + '] UNION ALL'
                      FROM [TestDB].SYS.TABLES tb 
                      INNER JOIN [TestDB].dbo.[tbl_tablesinfo] tbl ON tb.name = tbl.TableNames
                      FOR XML PATH('')), 1, 1, '');

    SET @var = LEFT(@var, LEN(@var) - 10);

    EXEC @var 

    RETURN
END

我收到一个错误:

“BEGIN”附近的语法不正确。

这样做的原因是使用 3k 表创建视图变得越来越慢并且需要大约 30 分钟的时间,所以我正在通过创建函数来寻找替代方案。

【问题讨论】:

  • 通过说returns table 而不定义表,您正在创建一个内联表值函数,其中只能有一个return select。如果您想要一个常规的表值函数,则需要定义返回表。请咨询docs

标签: sql sql-server tsql sql-server-2012


【解决方案1】:

docs中明确表示:

用户定义的函数不能使用动态 SQL 或临时表。 允许使用表变量。

这意味着您需要使用存储过程,这还不错,因为您仍然可以根据需要将数据插入表中:

INSERT INTO @Table
EXEC [dbo].[stored_procedured_name]

INSERT INTO #Table
EXEC [dbo].[stored_procedured_name]

因此,在您的情况下,您将拥有:

CREATE PROCEDURE udf_alldata
AS
BEGIN
    DECLARE @Var VARCHAR(MAX) = ''

    SELECT 
        @Var = STUFF((SELECT ' SELECT * FROM [' + tbl.TableNames + '] UNION ALL'
                      FROM [TestDB].SYS.TABLES tb 
                      INNER JOIN [TestDB].dbo.[tbl_tablesinfo] tbl ON tb.name = tbl.TableNames
                      FOR XML PATH('')), 1, 1, '');

    SET @var = LEFT(@var, LEN(@var) - 10);

    EXEC sp_executesql @var 

    RETURN
END

注意,实际上您可以执行dynamic T-SQL in function,但这是使用 SQL CLR 的特殊情况。我可以告诉你如何做到这一点,但最好还是坚持存储过程。

【讨论】:

    【解决方案2】:
    1. 您不能在 SQL 函数中使用动态查询...
    2. 函数只能返回标量值或表...
    3. 相反,您可以使用存储过程...

    【讨论】:

    • 虽然这在技术上是正确的,但它并不是一个高质量的答案......最好作为评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-27
    • 2014-11-27
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    相关资源
    最近更新 更多