2012-06-29 55 views
7

私の要件に応じて関数を作成しようとしています。ユーザ定義関数に一時テーブルを作成、削除、挿入する

しかし、作成または#tempTableを落としていたときのように、それはエラーを与えている:私の理解がある

関数内で副作用演算子「ドロップオブジェクトの無効な使用

関数内でcreate,dropまたはinsertの演算を#temptableに設定することはできません。

これは間違いありませんか?

マイSQL:正しい

CREATE FUNCTION [dbo].[RT_ResultFunction] 
(
    Id VARCHAR(4000) 
) 
RETURNS @RT_ResultFunction TABLE 
( 
    Id VARCHAR(20) 
    , Name varchar(20) 
    ,Balance Int 
) 
AS 
BEGIN 
    IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL 
     DROP TABLE #tempTable 

    SELECT Id, COUNT(Balance) 
    INTO #tempTable 
    'Balance' FROM Table1 

    INSERT @RT_ResultFunction 
     SELECT T1.ID,T1,NAME,T2,Balance 
     FROM Table2 T1, 
       #tempTable T2 
     WHERE T1.ID = T2.ID 

    RETURN 
END 
+1

ビットはあなたのSQLについて混乱します。 #tempTableからドロップダウンした後に選択する方法 - 決して再作成されません。 –

+0

更新された投稿 –

+0

を探してください。この問題を解決するには、関数内の#temptableのポイントを説明してください。また、Idパラメータを使って何をするか。 –

答えて

19

は - あなたがすることはできません側もたらす文:ここから

:できませんBEGIN ... ENDブロックでhttp://msdn.microsoft.com/en-us/library/aa175085(v=sql.80).aspx

ステートメント副作用がある。 機能の副作用は、データベーステーブルへの変更 のように、機能の外にスコープがある リソースの状態の永続的な変更です。関数内の ステートメントによって行われる唯一の変更は、ローカルカーソルまたは変数など、 関数のローカルオブジェクトへの変更です。 データベーステーブルへの変更、 関数に対してローカルではないカーソルに対する操作、電子メールの送信、カタログ変更の試行、および ユーザーに返される結果セットの生成は、 で実行できないアクションの例です機能。

は内からは一時テーブルにアクセスできません:

あなたもあなたのDROP書なしで、見つけるだろうどのような、一時テーブルにアクセスしようとするが(例えばSELECT ... INTO #TMPなど)あなたのメッセージを与えることです関数

@Demsが指摘しているように、テーブル変数を使用することができます。これらは変数なので、関数内でスコープが設定されているため、副作用はありません。

あなたの関数は、として実行されることがあります

... 

BEGIN 
    DECLARE @tempTable table (id varchar(20), rows int) 

    insert @tempTable 
    SELECT Id, COUNT(Balance) 
    FROM Table1 

    INSERT @RT_ResultFunction 
     SELECT T1.ID,T1,NAME,T2,Balance 
     FROM Table2 T1, 
       @tempTable T2 
     WHERE T1.ID = T2.ID 

    RETURN END 

テストか何かが、あなたはその要旨を取得できません。

+3

しかし、テーブル変数を使用することができます。あなたの答えに問題を解決する際にOPを助けるためにあなたの答えに追加するのに役立つ事実は何でしょうか?;); – MatBailie

+0

@Dems:良い点 - 詳細で更新されました。 –

+0

MSDNのドキュメントを読んだ後、自分の 'function'で' Stored Procedure'を呼び出すことで、テーブルからの実データ( 'INSERT' /' UPDATE'/'DELETE')を変更することができますか?私はあなたができないと思いますが、私はむしろエラーが生成されることを確信しています。あなたがそれを知っているかどうか教えてください。 :) –

2

この関数で#tempテーブルが必要な理由、または最初にマルチステートメントのTVFである理由はわかりません。以下は、はるかに効率的(私は@Idパラメータの目的を理解していないが)次のようになります。

CREATE FUNCTION [dbo].[RT_ResultFunction] 
(
    @Id VARCHAR(4000) 
) 
RETURNS TABLE 
WITH SCHEMABINDING 
AS 
    RETURN 
    (
    SELECT T2.ID, T2.NAME, T1.Balance 
    FROM 
    (
     SELECT ID, Balance = COUNT(Balance) 
     FROM dbo.Table1 
     GROUP BY ID 
    ) AS T1 
    INNER JOIN dbo.Table2 AS T2 
    ON T1.ID = T2.ID 
); 

ジョンが指摘したように、私は次のように、それはまた、再書き込みができると思います、それはです実際に私はそれを書き始めたが、これらのいずれかが実際にあなたが返すようにしようとしているデータを返す場合、私は確認する方法がありませんか:

CREATE FUNCTION [dbo].[RT_ResultFunction] 
(
    @Id VARCHAR(4000) 
) 
RETURNS TABLE 
WITH SCHEMABINDING 
AS 
    RETURN 
    (
    SELECT T2.ID, T2.NAME, Balance = COUNT(T1.Balance) 
    FROM dbo.Table1 AS T1 
    INNER JOIN dbo.Table2 AS T2 
    ON T1.ID = T2.ID 
    GROUP BY T2.ID, T2.NAME 
); 
+0

True - この場合、一時テーブルは「贅沢」のビットですが、いずれにしてもカバーするのに便利なポイントです。 (また、内側の列にエイリアスが必要です)。 –

+0

@Jon IDと名前は異なるテーブルから来ています。私はスキーマやデータを知らないので、元のクエリに真実を残そうとしました。 –

0

私は他の側面

をテストしていない @使う代わりに#を削除