カテゴリー別アーカイブ: 動的SQL

動的SQL(4)

ITコーディネータのシュウです。
IMG_0277

会社の人が広島に行ったときに、夕方近くに平和公園に散歩がてら立ち寄って撮った、原爆ドームの写真です。昔、小学校の修学旅行で広島の平和公園に行ったことがあり、千羽鶴がたくさんつるしてあったのを見た記憶がありますね。子供心に、戦争や原子爆弾の被害が二度とあってはならないと強く感じました。

<本日の題材>
動的SQL(SQL Server)

今回は、SQL Serverの場合の動的SQLの続きで、sp_executesql システムストアドプロシージャを利用した例です。

構文
sp_executesql [ @stmt = ] statement
[
{ , [ @params = ] N'@parameter_name data_type [ OUT | OUTPUT ][ ,...n ]' }
{ , [ @param1 = ] 'value1' [ ,...n ] }
]

@stmtにはパラメータを含めることができ、パラメータ定義リスト(@params=..)とパラメータ値リスト(@param1=..)の両方に指定する必要があります。

例)受注テーブルから、指定した受注日と決済金額の条件に合った受注データを抽出する例で、条件句(WHERE句)にパラメータ変数を用いています。

DECLARE @sql_stmt nvarchar(500)
DECLARE @tab_Name nvarchar(30) = 'dbo.受注テーブル'
DECLARE @param nvarchar(200)
SET @sql_stmt = N'SELECT * FROM ' + @tab_Name
SET @sql_stmt = @sql_stmt + N' WHERE 受注日= @p1_date'
SET @sql_stmt = @sql_stmt + N' AND 決済金額>= @p2_kingaku'
SET @param = N'@p1_date varchar(8), @p2_kingaku int'

EXEC sp_executesql@sql_stmt
, @param
, @p1_date = '20141029'
, @p2_kingaku = 300000

結果は、以下
executesql_2結果

条件として、受注日(@p1_date)に「20141029」、決済金額(@p2_kingaku)に「300000」以上をパラメータとして与えた場合の、受注テーブルのデータが抽出されました。

※)注意点として、最終的に変数@sql_stmtに設定したSQL文が正しいSQL文になるように、FROM句やWHERE句、AND句などの前後に空白をきちんと入れておく必要があります。(前回投稿の例でもこの点は同じですが)
もし、上記の例でWHEREの前の空白を入れていないと、エラーになります。上記をストアドプロシージャにした場合は、プロシージャのコンパイルはできるけれども、実行時にエラーになってしまうということが発生します。

executesql_2結果error2

また、パラメータを繰り返し変更しながらデータを取得するようなケースで、sp_executesql を利用することでかなりレスポンスを改善できる場合がありますが、それについては次回以降にまた機会を改めて、題材として取り上げようと思います。

今日は以上まで

にほんブログ村 IT技術ブログへ
にほんブログ村

動的SQL(3)

ITコーディネータのシュウです。
003

コスモスがいっぱい咲いてました。ちょっと前の台風で、結構倒れてしまっていたのですが、何とか復活して頑張って咲いています。

<本日の題材>
動的SQL(SQL Server)

今回は、SQL Serverの場合の動的SQLについての内容です。SQL Serverの場合は、EXECUTEステートメント、もしくは、sp_executesql システムストアドプロシージャを利用します。

例)
テーブル名や項目名を変数化して、指定したテーブルから必要な項目についてのデータを抽出する動的SQLの例です。EXECUTEステートメントを使用した場合です。

受注テーブルのデータを指定した条件で抽出します。
その前に、データを確認
SELECT * FROM dbo.受注テーブル
ORDER BY 受注NO;
受注テーブル全件ms

受注テーブルの定義は、Oracleのときと同じ
受注テーブル定義ms

SQLは以下:

DECLARE @tab_name VARCHAR(30)
DECLARE @Col_name VARCHAR(100)
DECLARE @Clause VARCHAR(200)
SELECT @tab_name = 'dbo.受注テーブル'
SELECT @Col_name = '顧客番号, 受注日, 決済金額'
SELECT @Clause = '受注日 BETWEEN ''20141028'' AND ''20141029'''

EXECUTE ('SELECT '+@Col_name+' FROM '+ @tab_name+' WHERE '+ @Clause)

パラメータとして、@tab_name にテーブル名、@Col_nameにカラム名、@Clauseには条件を渡し、それを実行します。
(SQL Serverでも、'で囲む文字列の中に'(シングルクォーテーション)を含む場合には、'を2つ連続して記述します)
また、EXECUTEは「EXEC」と省略することもできます。

結果は、以下
受注テーブル結果1ms

受注日が20141028~20141029の期間内での顧客番号、受注日、決済金額を抽出しています。
この各パラメータを変更すれば、動的に対象のテーブル、項目、条件を設定できます。以下は変更した場合の例。

DECLARE @tab_name VARCHAR(30)
DECLARE @Col_name VARCHAR(100)
DECLARE @Clause VARCHAR(200)
DECLARE @sql_stmt VARCHAR(400)
SELECT @tab_name = 'dbo.受注テーブル'
SELECT @Col_name = '顧客番号, 決済金額'
SELECT @Clause = '決済金額 > 300000'
SELECT @sql_stmt = 'SELECT '+@Col_name+' FROM '+ @tab_name+' WHERE '+ @Clause

EXEC (@sql_stmt)

結果は、以下
受注テーブル結果2ms

ここでは、最終的に @sql_stmt に組み合わせたSELECT文セットして、それを実行しています。決済金額が 300000円以上の顧客について、顧客番号と決済金額を表示できました。

今日は以上まで

にほんブログ村 IT技術ブログへ
にほんブログ村

動的SQL(2)

ITコーディネータのシュウです。
IMG_0294
きれいな白い渡り鳥?が川辺に止まっているのを偶然撮った写真です。シラサギでしょうか?
昔から、シラサギは縁起がいい鳥と言われているようで、ときに、田んぼにシラサギがいっぱいいるのを見たことがあって、ものすごく縁起がいい!と感動したことを覚えています。
シラサギは、汚い田んぼや河川には住まないとされていて、シラサギのいるところはきれいなところだといえるようですね。

<本日の題材>
動的SQL(Oracle)

今回は、前回に引き続いて動的SQLについての内容です。前回は動的なDDL文をEXECUTE IMMEDIATE文を使用して実行する例を取り上げましたが、今回は、動的なDML文を実行する例です。

例)対象レコードの件数を確認した後に、レコードを削除するSQLで、対象のテーブル名とWhereの条件文をパラメータとして渡すプロシージャ(動的なDML文)

CREATE OR REPLACE PROCEDURE del_table(tab_name VARCHAR2, clause VARCHAR2)
IS
Sql_stmt1 VARCHAR2(100);
Sql_stmt2 VARCHAR2(100);
V_COUNT NUMBER(4);

BEGIN
Sql_stmt1 := 'SELECT COUNT(*) FROM '||tab_name||' WHERE ' || clause;
DBMS_OUTPUT.PUT_LINE(Sql_stmt1);
EXECUTE IMMEDIATE Sql_stmt1 INTO V_COUNT;
DBMS_OUTPUT.PUT_LINE('件数は '||V_COUNT||' 件です');

Sql_stmt2 := 'DELETE FROM '||tab_name||' WHERE ' || clause;
DBMS_OUTPUT.PUT_LINE(Sql_stmt2);
EXECUTE IMMEDIATE Sql_stmt2;
COMMIT;
END;
/

※DBMS_OUTPUT パッケージは標準出力にメッセージを表示することができ、デバッグ目的などでよく使用されます。

受注テーブルのデータを指定した条件で削除します。
その前に、データを確認

SELECT * FROM 受注テーブル
ORDER BY 受注NO;
受注テーブル結果1

受注テーブルの定義は以下:
受注テーブル定義

プロシージャの実行
パラメータとして、'受注テーブル'、'受注日 = ''20141024''' を渡します。
('で囲む文字列の中に'(シングルクォーテーション)を含む場合には、'を2つ連続して記述する必要があります)

EXECUTE del_table('受注テーブル','受注日 = ''20141024''');
execute_del

処理の結果、受注テーブルを再度確認します。
SELECT * FROM 受注テーブル
ORDER BY 受注NO;
受注テーブル結果2

受注日が「20141024」のデータが削除され、delete文が実行されたことが確認できました。

パラメータのテーブル名、条件を別の値にすれば、異なるテーブルから異なる条件のデータを削除することができます。

今日は以上まで

にほんブログ村 IT技術ブログへ
にほんブログ村

動的SQL(1)

ITコーディネータのシュウです。

IMG_0895

娘がこの夏にボランティアの関係でカンボジアに行ってきたときに撮った写真です。

写真はメコン川で、中国チベット高原を源流としてミャンマー・ラオス国境、タイ・ラオス国境、カンボジア・ベトナムを通り南シナ海に抜ける、世界でも有数の国際河川の一つです。
カンボジアではこの夏も、豪雨のためメコン川流域で洪水が起きて、大変だったようです。
娘が訪問した村では、下の写真のように、水害で家の下のほうは水につかってしまい、船にたまった水をかきだしている様子を撮っています。(どの家も交通手段として船を持っているとのこと)
日本も台風や地震、火山噴火など様々な災害が起きており、犠牲になった方のご冥福を祈るばかりですが、世界でもいろいろと災害があって、その中で暮らして行かなければならないので、苦労が多いですね。

IMG_1042

<本日の題材>
動的SQL(Oracle)

通常のSQLでは、UPDATEやINSERTなどの処理をどの表のどの項目に対して行うのか、というのがあらかじめ明確になっているのですが、一部のケースでは、様々なSQL文を実行時に作成、またはパラメータとして受けて処理を行うという場合があります。
この場合は、SQL文の構成は実行時まで明確ではなく、実行のたびに変わる可能性があり、これを動的SQLといいます。この動的SQLは実行時にプログラムに入力、または作成される文字列に格納されるかたちになります。

動的SQLを実行する方法としては、EXECUTE IMMEDIATE文を使用する方法、カーソル変数を使用する方法などがありますが、今回は、EXECUTE IMMEDIATE文を使用する方法を取り上げます。

例)パラメータとして、削除するテーブル名を渡すプロシージャ(動的なDDL文)

CREATE OR REPLACE PROCEDURE truncate_table(tab_name VARCHAR2)
IS
Sql_stmt VARCHAR2(100) := 'TRUNCATE TABLE '|| tab_name;
BEGIN
EXECUTE IMMEDIATE Sql_stmt;
END;
/

テーブル:商品マスタのデータを削除します。
その前に、データを確認

SELECT * FROM 商品マスタ;
商品マスタ

プロシージャの実行
パラメータとして、「商品マスタ」を渡します。

EXECUTE truncate_table(‘商品マスタ’);
execute1

SELECT COUNT(*) FROM 商品マスタ;
execute_結果1

データが1件もなくなり、truncate文が実行されたことが確認できました。
今日は以上まで

にほんブログ村 IT技術ブログへ
にほんブログ村