わかりました、新しい回答。賞金が私をより創造的にするほどではありません、むしろ私は私がまっすぐに考えていない解決策を提案するための制約をあまり感じません:)
(私はまだあなたが保存されたルーチンを絶対に避けたいと思っていると思います)
解決策#1:プリペアドステートメントを使用する
upradesスクリプトが単純であると仮定します。
ALTER TABLE t ADD COLUMN c INT DEFAULT 1
では、これはどうですか。
SET @version := '1';
SELECT CASE val
WHEN @version THEN
'ALTER TABLE t ADD COLUMN c INT DEFAULT 1'
ELSE 'SELECT ''Wrong version. Nothing to upgrade.'''
END
INTO @stmt
FROM meta
WHERE name = 'Version';
PREPARE stmt FROM @stmt;
EXECUTE stmt;
明らかな欠点:
- 個々のステートメントごとにこれを記述する必要があるため、混乱とオーバーヘッドを解消します(
PREPARE
複数のステートメントをバッチ処理することはできません)
- アップグレードスクリプトの各ステートメントを文字列として記述しなければならないため、さらに煩わしい...
- すべてのステートメントをで記述および実行できるわけではありません
PREPARE
解決策#2:接続を強制終了するための1つのプリペアドステートメント
リンクしたソリューションも嫌いなことをすでに指摘しました...それはKILL
ステートメントのせいですか、それともストアド関数のせいですか?ストアド関数が原因である場合は、次のことを回避できます。
SET @version := '1';
SELECT CASE val
WHEN @version THEN 'SELECT ''Performing upgrade...'''
ELSE CONCAT('KILL CONNECTION', connection_id())
END
INTO @stmt
FROM meta
WHERE name = 'Version';
PREPARE stmt FROM @stmt;
EXECUTE stmt; -- connection is killed if the version is not correct.
-- remainder of the upgrade script goes here...
mysql
--skip-reconnect
接続が切断された場合にステートメントを実行できないようにするオプションを指定して開始する必要があります
私はこの欠点を回避しPREPARE
、ユーザーの削除や特権の取り消しなど、現在の接続をブロックする他の目的に使用しようとしました。残念ながら、それは意図したとおりには機能しません(いいえ、後も機能しませんFLUSH PRIVILEGES
)
解決策3:mysqlプロキシを使用して傍受する
さらに別の解決策:プロキシを使用します。mysqlプロキシ(http://forge.mysql.com/wiki/MySQL_Proxyを参照)を使用すると、カスタムコマンドを解釈するカスタムインターセプトスクリプトをluaで記述できます。これを使用して、必要な制御構造を追加できます。欠点:独自のミニ言語を設計し、それを解釈するためにluaを学ぶ必要があります:)