Azureデータウェアハウス データベースでUDFを作成して使用することに、ここの誰もが運がよかったですか?オンプレミスのウェアハウスをSQL Server 2014からAzure datawarehouseに移行している最中に、UDFで問題が発生しました。
CREATE FUNCTION dbo.fn_GetImpliedRate (@Multiple float, @term int)
RETURNS float
AS
BEGIN
DECLARE @ImpInt float
IF(@Term = 1)
SET @ImpInt = (select [1] from dbo.ImpliedRate where Multiple = @Multiple);
IF(@Term = 2)
SET @ImpInt = (select [2] from dbo.ImpliedRate where Multiple = @Multiple);
IF(@Term = 3)
SET @ImpInt = (select [3] from dbo.ImpliedRate where Multiple = @Multiple);
IF(@Term = 4)
SET @ImpInt = (select [4] from dbo.ImpliedRate where Multiple = @Multiple);
RETURN @ImpInt
END;
GO
このUDFはSQL Server 2014で完全に機能します。これをAzureデータウェアハウスで作成すると、作成されますが、クエリを実行しても機能しません。 NULL
を返します。ターゲットテーブルが存在するかどうかなど、明らかなことをすべて確認しました。私はAzureデータウェアハウスの CREATE FUNCTION ドキュメントを確認しましたが、int
をdecimal
に変換するサンプルUDFがあります。これはAzure DWで問題なく動作します。 select
を持つ単純な関数を書いた瞬間、失敗しました。残念ながら、ここでのAzureのドキュメントはあまり役に立ちません。この問題に遭遇した人がいるかどうか疑問に思いました。はいの場合、どのように解決しましたか?
私は別のユースケースをテストしたところ、うまくいきませんでした:
CREATE function [dbo].[fn_GetNumberBusinessDays]
(
@StartDate datetime,
@EndDate Datetime
)
returns int
as
begin
DECLARE @NDAYS INT = 0
SELECT @NDAYS =
ISNULL( (DATEDIFF(dd, @StartDate, @EndDate) + 1)
-(DATEDIFF(wk, @StartDate, @EndDate) * 2)
-(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END) - 1 ,0) + 1
SELECT @NDAYS = @NDAYS - COUNT(*)
FROM dbo.FedHolidays
WHERE DateOfHoliday BETWEEN @StartDate AND @EndDate
RETURN @NDAYS
end
GO
Azure DWの関数は、ユースケースのようにテーブルにアクセスするselectステートメントをサポートしていません。 CREATE FUNCTION(SQLデータウェアハウス) を参照してください。
function_body
データベースデータ(テーブルまたはビュー)を参照しない一連のTransact-SQLステートメントが関数の値を定義することを指定します。
関数がDWで作成されていることを再確認できますか?
Azure SQL Data Warehouseは、UDFのサポートに制限があります。構文SELECT @var =
はまだサポートされていません。代わりに、DECLARE @var int =
またはSET @var =
を使用する必要があります。 SQL DW UDFは、まだユーザーテーブルのクエリもサポートしていません。新機能に投票するには フィードバックページ を使用してください。
Azure SQL Data Warehouseには、互換性のないデータ型、インライン関数、ヒントの使用、RETURN
ステートメントの使用などの問題をピックアップするデータウェアハウス移行ユーティリティ(利用可能 こちら )があります。 INSERT ... EXEC
および他の多く:
残念ながら、それはテーブルを参照するスカラー関数をピックアップせず、実際にそうするべきです。ただし、特定の関数の場合、それは単なるビュー(または別のテーブル)でもかまいません。たとえば、
CREATE VIEW dbo.vw_ImpliedRates
AS
SELECT 1 term, [1] impliedRate, Multiple
FROM dbo.ImpliedRate
UNION ALL
SELECT 2 term, [2], Multiple
FROM dbo.ImpliedRate
UNION ALL
SELECT 3 term, [3], Multiple
FROM dbo.ImpliedRate
UNION ALL
SELECT 4 term, [4], Multiple
FROM dbo.ImpliedRate;
GO
CREATE TABLE dbo.test
(
Multiple FLOAT NOT NULL,
Term INT NOT NULL
);
GO
INSERT INTO dbo.test ( Multiple, Term )
VALUES
( 0.001, 1 ), ( 0.001, 2 ), ( 0.001, 3 ), ( 0.001, 4 );
GO
SELECT impliedRate, v.Multiple
FROM dbo.test t
INNER JOIN dbo.vw_ImpliedRates v
ON t.Multiple = v.Multiple
AND t.Term = v.Term;
SELECT *
FROM dbo.vw_ImpliedRates
WHERE Multiple = 0.001
AND Term = 2
私はこれをAzure SQL Data Warehouseで試してみましたが、完全にうまくいきました。
また、SQL Serverのスカラー関数は、テーブルに対して呼び出されたときに適切にスケーリングされないことも知っておく必要があります。AzureSQLデータウェアハウスに適したボリューム(つまり、数十億行)がある場合は、スカラー関数の使用を再考する必要があります。とにかく。たとえば、CTAS
を使用してより多くの手続き型コードを記述することは、この非常に強力なプラットフォームを適切に使用できる優れたアプローチです。