在Azure SQL DW中更新?

时间:2018-03-27 14:10:13

标签: sql-update azure-sqldw

我在尝试执行UPDATE FROM查询的Azure SQL DW中收到错误。错误是UPDATE和DELETE语句中的" FROM子句不能包含子查询源或连接"

这仅仅是针对SQL DW吗?否则我不会发现此查询有任何问题。如果它是SQL DW的限制,可以选择什么?

-- Permanent fact table with 5 billion rows
CREATE TABLE FactTable (Id1 INT, Id2 INT, EmailAddress NVARCHAR(100), Value1 INT)
WITH (DISTRIBUTION = HASH(EmailAddress));

-- Staging fact table with 10 million rows    
CREATE TABLE StageTable (Id1 INT, Id2 INT, EmailAddress NVARCHAR(100), Value1 INT)
WITH (DISTRIBUTION = HASH(EmailAddress), HEAP);

-- Add a secondary index that should help with joining to StageTable
CREATE NONCLUSTERED INDEX ix ON FactTable (Id1, Id2);

UPDATE fact
SET
   Value1 = CASE WHEN stage.Value1 > fact.Value1 THEN stage.Value1 ELSE fact.Value1 END
FROM FactTable AS fact
INNER JOIN StageTable AS stage ON fact.Id1 = stage.Id1 AND fact.Id2 = stage.Id2

3 个答案:

答案 0 :(得分:2)

根据the documentation Azure SQL数据仓库支持UPDATE但不支持FROM子句中的ANSI连接。您可以使用CTAS来解决问题。简单的两表更新:

UPDATE dbo.FactTable
SET
   Value1 = CASE WHEN stage.Value1 > dbo.FactTable.Value1 THEN stage.Value1 ELSE dbo.FactTable.Value1 END
FROM dbo.StageTable AS stage
WHERE dbo.FactTable.Id1 = stage.Id1 
  AND dbo.FactTable.Id2 = stage.Id2;

CTAS更复杂的例子,从main UPDATE documentation page批发复制:

-- Create an interim table
CREATE TABLE CTAS_acs
WITH (DISTRIBUTION = ROUND_ROBIN)
AS
SELECT  ISNULL(CAST([EnglishProductCategoryName] AS NVARCHAR(50)),0)    AS [EnglishProductCategoryName]
,       ISNULL(CAST([CalendarYear] AS SMALLINT),0)                      AS [CalendarYear]
,       ISNULL(CAST(SUM([SalesAmount]) AS MONEY),0)                     AS [TotalSalesAmount]
FROM    [dbo].[FactInternetSales]       AS s
JOIN    [dbo].[DimDate]                 AS d    ON s.[OrderDateKey]             = d.[DateKey]
JOIN    [dbo].[DimProduct]              AS p    ON s.[ProductKey]               = p.[ProductKey]
JOIN    [dbo].[DimProductSubCategory]   AS u    ON p.[ProductSubcategoryKey]    = u.[ProductSubcategoryKey]
JOIN    [dbo].[DimProductCategory]      AS c    ON u.[ProductCategoryKey]       = c.[ProductCategoryKey]
WHERE   [CalendarYear] = 2004
GROUP BY
        [EnglishProductCategoryName]
,       [CalendarYear]
;

-- Use an implicit join to perform the update
UPDATE  AnnualCategorySales
SET     AnnualCategorySales.TotalSalesAmount = CTAS_ACS.TotalSalesAmount
FROM    CTAS_acs
WHERE   CTAS_acs.[EnglishProductCategoryName] = AnnualCategorySales.[EnglishProductCategoryName]
AND     CTAS_acs.[CalendarYear]               = AnnualCategorySales.[CalendarYear]
;

--Drop the interim table
DROP TABLE CTAS_acs
;

答案 1 :(得分:1)

我发现ASDW(和APS / PDW)是一个很好的做法,可以避免瘟疫之类的批量更新。

这是一种纯CTAS替代方案,在您更新大部分行的情况下会更快。

它假定id1是一个相对好的分发键,并且分段行的数量小于事实行,使复制可行。该策略应该消除节点之间的数据移动。

如果你有一个非常大的临时表,在每个表中创建一个代理列,它是id1和id2的组合,然后通过该列的哈希分配两个表,将会提供更好的性能。

android:paddingBottom="@dimen/dp10"

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/dp10">

答案 2 :(得分:0)

简化您的尝试将起作用。只需删除连接并从另一个表更新一个表。

update FactTable
set this = that
from StageTable s where s.something = FactTable.something

这是否是最佳方法取决于您的具体情况,但它会在不引发错误的情况下执行。