【问题标题】:Is there any alternative of CREATE TYPE in SQL as CREATE TYPE is Not supported in Azure SQL data warehouseSQL 中是否有 CREATE TYPE 的替代方案,因为 Azure SQL 数据仓库不支持 CREATE TYPE
【发布时间】:2019-03-15 08:29:30
【问题描述】:

我正在尝试执行此查询,但由于 azure 数据仓库不支持用户定义(创建类型)类型。我想在存储过程中使用它。

CREATE TYPE DataTypeforCustomerTable AS TABLE(
    PersonID int,
    Name varchar(255),
    LastModifytime datetime
);
GO

CREATE PROCEDURE usp_upsert_customer_table @customer_table DataTypeforCustomerTable READONLY
AS

BEGIN
  MERGE customer_table AS target
  USING @customer_table AS source
  ON (target.PersonID = source.PersonID)
  WHEN MATCHED THEN
      UPDATE SET Name = source.Name,LastModifytime = source.LastModifytime
  WHEN NOT MATCHED THEN
      INSERT (PersonID, Name, LastModifytime)
      VALUES (source.PersonID, source.Name, source.LastModifytime);
END
GO

CREATE TYPE DataTypeforProjectTable AS TABLE(
    Project varchar(255),
    Creationtime datetime
);
GO

CREATE PROCEDURE usp_upsert_project_table @project_table DataTypeforProjectTable READONLY
AS

BEGIN
  MERGE project_table AS target
  USING @project_table AS source
  ON (target.Project = source.Project)
  WHEN MATCHED THEN
      UPDATE SET Creationtime = source.Creationtime
  WHEN NOT MATCHED THEN
      INSERT (Project, Creationtime)
      VALUES (source.Project, source.Creationtime);
END

有没有其他方法可以做到这一点。

【问题讨论】:

    标签: azure azure-sql-database sql-data-warehouse azure-database-mysql


    【解决方案1】:

    您在那里遇到了一些挑战,因为您尝试转换的大部分内容都不是在 ASDW 上做事的方式。

    首先,正如您所指出的,不支持 CREATE TYPE,并且没有等效的替代方案。

    接下来,代码似乎正在对表进行单次插入。这在 ASDW 上真的很糟糕,性能会很糟糕。

    接下来,ASDW 还没有 MERGE 语句。那是因为 UPDATE 不是处理不断变化的数据的最佳方式。

    最后,存储过程在 ASDW 上的工作方式略有不同,它们不是编译的,而是在每次调用过程时进行解释。存储过程非常适合大块的表级逻辑,但不推荐用于单行操作的大容量调用。

    我需要更多地了解用例才能提出具体建议,但一般来说,您需要考虑表格而不是行。尤其要关注处理 ELT 的 CREATE TABLE AS (CTAS) 方式。

    这是一个很好的链接,它显示了如何使用 CTAS 处理 Merge/Upsert 的等效项:

    https://docs.microsoft.com/en-us/azure/sql-data-warehouse/sql-data-warehouse-develop-ctas#replace-merge-statements

    如您所见,它一次处理两个表,而不是一行。这意味着您需要查看调用存储过程示例的逻辑。

    如果您全神贯注地在 CTAS 中做所有事情,并在分发方面分开做,那么您就可以拥有一个高性能的数据仓库。

    【讨论】:

    • 好东西 Ron,喜欢你在 Azure SQL 数据仓库上的帖子。我不确定我是否看到单行模式 - TYPE 可能包含许多记录,而作为 MERGE 一部分的 VALUES 语句将插入许多记录。他们基本上需要将表类型转换为临时表,并根据需要将 MERGE 拆分为单独的 INSERT / UPDATE / DELETE 语句。
    • Bob 在 UPDATE 与 CTAS 上是正确的,我过分强调了极端情况。如果您要修改大部分表格,请使用 CTAS。如果您只更改较小的百分比,请使用如下所示的 UPDATE/DELETE。
    【解决方案2】:

    Azure SQL 数据仓库中的临时表与盒装产品 SQL Server 或 Azure SQL 数据库的行为略有不同 - 它们存在于会话级别。因此,您所要做的就是将您的 CREATE TYPE 语句转换为临时表,并根据需要将 MERGE 拆分为单独的 INSERT / UPDATE / DELETE 语句。

    例子:

    CREATE TABLE #DataTypeforCustomerTable (
        PersonID        INT,
        Name            VARCHAR(255),
        LastModifytime  DATETIME
    )
    WITH
    (
        DISTRIBUTION = HASH( PersonID ),
        HEAP
    )
    GO
    
    CREATE PROCEDURE usp_upsert_customer_table 
    AS
    
    BEGIN
    
        -- Add records which do not already exist
        INSERT INTO customer_table ( PersonID, Name, LastModifytime )
        SELECT PersonID, Name, LastModifytime
        FROM #DataTypeforCustomerTable AS source
        WHERE NOT EXISTS
            (
            SELECT *
            FROM customer_table target
            WHERE source.PersonID = target.PersonID
            )
    ...
    

    只需加载临时表并执行存储的过程。有关临时表范围的更多详细信息,请参阅here

    如果您要更改表的大部分,那么您应该考虑使用CTAS 方法来创建一个新表,然后按照 Ron 的建议重命名它。

    【讨论】:

    • 你好,@wBob 我曾尝试运行此查询,但出现如下错误:-“无法执行查询。错误:第 15 行的解析错误,第 10 列:''附近的语法不正确) ’。”你能更正整个查询吗?它应该可以在 Azure SQLDWH 上轻松运行。
    • 嗨@gauravmodi,我的代码是一个示例,说明了我无法为您编写整个代码 - 只有您知道您的数据和架构。
    猜你喜欢
    • 2017-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多