【问题标题】:Table Variables in Azure Data WarehouseAzure 数据仓库中的表变量
【发布时间】:2018-01-17 20:53:54
【问题描述】:

在 SQL Server 数据库中,可以像这样使用表变量:

declare @table as table (a int)

在 Azure 数据仓库中,这会引发错误。

第 1 行第 19 列解析错误:'table' 附近的语法不正确

在 Azure 数据仓库中,您可以使用临时表:

create table #table (a int)

但不在函数内部。

消息 2772,级别 16,状态 1,第 6 行无法访问临时表 从函数内部。

来自微软的This document 说,

◦必须分两步声明(而不是内联):◾CREATE TYPE 我的类型作为表 ...; ,然后◾DECLARE @mytablevariable my_type;。

但是当我尝试这个时:

create type t as table (a int);
drop type t;

我明白了:

消息 103010,第 16 级,状态 1,第 1 行解析错误,第 1 行,第 1 列: 8: 'type' 附近的语法不正确。

我的目标是在使用临时表的 Azure 数据仓库中创建一个函数。可以实现吗?

编辑从这里开始

请注意,我并不是在寻找其他方法来创建一个特定的功能。我实际上已经做到了并继续前进。我是一名资深程序员,但也是一名 Azure 数据仓库新手。我想知道是否可以在 Azure 数据仓库函数中加入一些临时表的概念。

【问题讨论】:

  • Azure 数据仓库不支持用户定义的类型。你可以在函数中使用 CTE 代替吗?
  • 如果必须,我可以解决这个问题,但我宁愿不这样做。我正在处理的功能结合了代码审查中提出的逻辑。 codereview.stackexchange.com/questions/185329/…
  • 你究竟想让你的函数在这里做什么?您最初编写的哪些 SQL 不起作用?
  • Code Review 的链接显示了我最初编写的 sql,但我是针对数据库编写的。当我尝试将其放入数据仓库功能时,我失败了。
  • 您链接到的那个 SQL 有 3 个返回的数据集。一个函数只能返回 1 个数据集/值。您希望返回哪个数据集?

标签: sql sql-server sql-data-warehouse


【解决方案1】:

好的,我相信这就是你所追求的。

首先,它使用表值函数,它比标量或多语句表值函数快得多。

其次,表变量或临时表没有用处,只是一些很好的奇怪字符串操作、一点数学和 CTE。绝对没有昂贵的WHILE 循环。

我已经根据链接中的示例对此进行了测试,它们都返回了预期值。

USE Sandbox;
GO
CREATE FUNCTION ValidateHealthNumber (@HealthNumber varchar(10))
RETURNS TABLE
AS
RETURN

    WITH Doubles AS(
        SELECT CONVERT(tinyint,SUBSTRING(V.HN,O.P,1)) AS HNDigit,
               CONVERT(tinyint,SUBSTRING(V.HN,O.P,1)) * CASE WHEN O.P % 2 = 0 THEN 1 ELSE 2 END ToAdd
        FROM (VALUES(@HealthNumber)) V(HN)
              CROSS APPLY (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9)) O(P)),
    Parts AS (
        SELECT CONVERT(tinyint,SUBSTRING(CONVERT(varchar(2),ToAdd),1,1)) AS FirstDigit, --We know that the highest value can be 18 (2*9)
               CONVERT(tinyint,SUBSTRING(CONVERT(varchar(2),ToAdd),2,1)) AS SecondDigit --so no need for more than 2 digits.
        FROM Doubles)
    SELECT CASE RIGHT(@HealthNumber, 1) WHEN 10 - RIGHT(SUM(FirstDigit + SecondDigit),1) THEN 1 ELSE 0 END AS IsValid
    FROM Parts;

GO

CREATE TABLE #Sample(HealthNumber varchar(10));
INSERT INTO #Sample
VALUES ('9876543217'), --Sample
       ('5322369835'), --Valid 
       ('7089771195'), --Valid
       ('8108876957'), --Valid
       ('4395667779'), --Valid
       ('6983806917'), --Valid
       ('2790412845'), --not Valid
       ('5762696912'); --not Valid

SELECT *
FROM #Sample S
     CROSS APPLY ValidateHealthNumber(HealthNumber) VHN;
GO
DROP TABLE #Sample
DROP FUNCTION ValidateHealthNumber;

如果你不明白这些,请尽管问。

【讨论】:

    【解决方案2】:

    不,你不能。无法在用户定义函数 (UDF) 中创建对象。请改用表变量。

    如果你想使用用户定义的类型,首先在 UDF 之外创建它,然后在 UDF 中将它用作变量类型。

    -- Create the data type
    CREATE TYPE TestType AS TABLE 
    (
        Id INT NOT NULL,
        Col1 VARCHAR(20) NOT NULL)
    GO
    
    -- Create the tabled valued function
    CREATE FUNCTION TestFunction
    ()
    RETURNS 
    @Results TABLE 
        (Result1 INT, Result2 INT)
    AS
    BEGIN
        -- Fill the table variable with the rows for your result set
        DECLARE @Var1 TestType;
    
        RETURN 
    END
    GO
    

    【讨论】:

    • 我的问题可能还不清楚,但是我创建类型的尝试并没有发生在函数内部。我运行了您的 create type 命令并得到了与我相同的结果。不过感谢您的努力。
    • 上述方法的问题在于,它会将函数转换为多语句表值函数,这些函数的性能通常非常糟糕(与 Scalar 一样或更差)。我们在这里需要更多信息,但如果可能,最好将其保留在单个语句 TVF 中。
    猜你喜欢
    • 1970-01-01
    • 2018-06-09
    • 2019-11-09
    • 1970-01-01
    • 2017-12-10
    • 2016-06-30
    • 1970-01-01
    • 2017-01-04
    • 2016-10-26
    相关资源
    最近更新 更多