T-SQL知らなかったメモマン
時間がないからといって API(に限らず)の設計を見切り発車で作成するのは くなかったな、と痛感した今日。
焦ってコンストラクションを行うほうが 結果としてリスクもコストも高くなる悪例でした。
ストアドファンクションでは副作用を伴う処理を行えない
副作用を伴う処理とは、 INSERT
/UPDATE
/DELETE
/EXEC PROCEDURE
など。
(PROCEDUREに関しては、一部の拡張ストアドプロシージャならOKだとか。要調査)
FUNCTION=関数という言葉を、関数型言語の意味の関数で捉えるとわかりやすい。 参照透過性というか。
exec sp_executesql
を使えば、FUCNTION内部からでも無理やり実行できなくはない…と思うが、
言語仕様としてやめとけっていうのに逆らうとろくなことがない。
PROCEDUREでやったほうがわかりやすくて綺麗になる。
あと地味に、BEGIN TRY〜END TRY
(CATCHも同様)も使えない。
これはちょっと理由がわからないな…。
Table型パラメータの誤算
ストアドプロシージャのOUTパラメータとして、Table型は使えない。
では可変で複数を取りうる値を返すにはどうするかというと、 statement_bodyにSELECT句を書けば、 結果セットとして返却可能。
ただし、通常のSELECTはすべて結果セットとして返却されてしまうので、API設計(というかパブリックなルーチン設計か?)としては あまりよろしくないかもしれない。
ではどうすればよいかというと、 変数に代入してあげれば、そのステートメントは結果にはならない。 Table型(や、独自ドメイン)はINパラメータとしては使える。
パラメータは2,100個まで。
()で囲めば、IF文の中でもSELECT句をかける。
毎度変数に代入してた…。可読性とのトレードオフになるかとは思うけど。
YYYYMMDD形式が厳密に正しい日付かどうか。
一応、IsDateという関数は提供されているが、
言語やフォーマット変えないと使えないっぽい。
CONVERT
使うとエラーになるし、困った。
邪道だけど、TRY-CATCH
でなんとかするか、と思ったが、 FUNCTIONでは使えない。 (アンチパターン)
うーん、8桁の確認と、substring
で分割してIsDate
にぶち込むか、
と思ったら、try_convert
なる関数があるようで。
変換不可ならNULLを返してくれる(もちろんIsNullと組み合わせればNullオブジェクトっぽくも出来る) 素敵関数。
可搬性は低そうだけど…。
STOREDのCREATE系(一応備忘録)
CREATE PROC[EDURE] proc_name ( @var1 type [READONLY], @var2 type = default OUT ) BEGIN -- 最低1行のステートメント END -- FUNCTIONはRETURNSが付く感じ。 -- TABLE型には()を付加して、通常のCreate Tableみたいなカラム定義する
SQL標準も学ばないとな、と決意を新たにしました。