1

I am trying to execute this query but as userdefined(Create type) types are not supportable in azure data warehouse. and i want to use it in stored procedure.

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

Is there any alternative way to do this.

wBob
  • 13,710
  • 3
  • 20
  • 37
gaurav modi
  • 39
  • 2
  • 9

2 Answers2

1

You've got a few challenges there, because most of what you're trying to convert is not the way to do things on ASDW.

First, as you point out, CREATE TYPE is not supported, and there is no equivalent alternative.

Next, the code appears to be doing single inserts to a table. That's really bad on ASDW, performance will be dreadful.

Next, there's no MERGE statement (yet) for ASDW. That's because UPDATE is not the best way to handle changing data.

And last, stored procedures work a little differently on ASDW, they're not compiled, but interpreted each time the procedure is called. Stored procedures are great for big chunks of table-level logic, but not recommended for high volume calls with single-row operations.

I'd need to know more about the use case to make specific recommendations, but in general you need to think in tables rather than rows. In particular, focus on the CREATE TABLE AS (CTAS) way of handling your ELT.

Here's a good link, it shows how the equivalent of a Merge/Upsert can be handled using a CTAS:

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

As you'll see, it processes two tables at a time, rather than one row. This means you'll need to review the logic that called your stored procedure example.

If you get your head around doing everything in CTAS, and separately around Distribution, you're well on your way to having a high performance data warehouse.

Ron Dunn
  • 2,971
  • 20
  • 27
  • 1
    Good stuff Ron, loving your posts on Azure SQL Data Warehouse. I'm not sure I see the single row pattern though - the `TYPE` could contain many records and the `VALUES` statement as part of a `MERGE` will insert many records. They basically need to convert the table types to temp tables and split the MERGE out into separate `INSERT` / `UPDATE` / `DELETE` statements as required. – wBob Mar 15 '19 at 13:11
  • Bob is correct on UPDATE vs CTAS, I've over-emphasised the extreme cases. If you're modifying a high percentage of the table use CTAS. If you're only changing a smaller percentage, use UPDATE/DELETE as shown below. – Ron Dunn Mar 16 '19 at 02:38
1

Temp tables in Azure SQL Data Warehouse have a slightly different behaviour to box product SQL Server or Azure SQL Database - they exist at the session level. So all you have to do is convert your CREATE TYPE statements to temp tables and split the MERGE out into separate INSERT / UPDATE / DELETE statements as required.

Example:

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
        )
...

Simply load the temp table and execute the stored proc. See here for more details on temp table scope.

If you are altering a large portion of the table then you should consider the CTAS approach to create a new table, then rename it as suggested by Ron.

wBob
  • 13,710
  • 3
  • 20
  • 37
  • hello, @wBob I have tried to run this query I got an error like:- "Failed to execute query. Error: Parse error at line: 15, column: 10: Incorrect syntax near ')'." can you please correct the whole query. that it should run easily on Azure SQLDWH. – gaurav modi Mar 18 '19 at 05:37
  • Hi @gauravmodi, my code is an *example* of how to approach the problem I cannot write your whole code for you - only you know your data and schema. – wBob Apr 04 '19 at 10:15