FM牛鍵屋本舗

プログラマ(弱)の日々精進系ブログ

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標準も学ばないとな、と決意を新たにしました。