ストアドファンクション⇒プロシージャ呼出し失敗

このQ&Aのポイント
  • 参考の通りに、ストアドプロシージャ作成SQL文を発行し、コマンドライン上からは、以下の通りの結果1となり、レコードがinsertされます。
  • ですが、testというストアドファンクションから呼び出してみましたが、以下の結果2の通り、失敗します。
  • 現在動作している環境では、どこでエラーが発生したかがわからず、ロガーの処理をなんとしても実装したいのですが、いろいろ試してみても、解決できませんでした。
回答を見る
  • ベストアンサー

ストアドファンクション⇒プロシージャ呼出し失敗する

参考の通りに、ストアドプロシージャ作成SQL文を発行し、 コマンドライン上からは、以下の通りの結果1となり、 レコードがinsertされます。 <結果1> mysql> call logger('ほげ', 'ホゲ'); Query OK, 1 row affected (0.01 sec) mysql> select * from PROCEDURE_LOG; +--------+--------+---------------------+ | NAME | QUERY | EXECUTE_DATE | +--------+--------+---------------------+ | ほげ | ホゲ | 2014-03-26 10:41:26 | +--------+--------+---------------------+ 1 row in set (0.00 sec) ですが、testというストアドファンクションから呼び出してみましたが、 以下の結果2の通り、失敗します。 <結果2> mysql> select test(); ERROR 1336 (0A000): Dynamic SQL is not allowed in stored function or trigger <test> BEGIN CALL logger('test','1'); RETURN CONCAT('END'); END 現在動作している環境では、どこでエラーが発生したかがわからず、 ロガーの処理をなんとしても実装したいのですが、 いろいろ試してみても、解決できませんでした。 ご教示のほど、よろしくお願いします。 <参考> http://treeapps.hatenablog.com/entry/20120106/p1 <ストアドプロシージャ作成SQL文(logger)> SET NAMES UTF8; delimiter // -- ログ出力 DROP PROCEDURE IF EXISTS logger// CREATE PROCEDURE logger( IN PROCEDURE_NAME TEXT, IN SQL_TEXT TEXT ) BEGIN DECLARE CNT INT; CREATE TABLE IF NOT EXISTS PROCEDURE_LOG ( NAME VARCHAR(64), QUERY TEXT, EXECUTE_DATE TIMESTAMP, KEY IDX1 (NAME, QUERY(64), EXECUTE_DATE) ) ENGINE=MYISAM DEFAULT CHARSET=UTF8; -- 古いログを削除 SELECT COUNT(*) INTO CNT FROM PROCEDURE_LOG; IF CNT >= 1000 THEN DELETE FROM PROCEDURE_LOG LIMIT 1; END IF; -- テーブルにログを記録 SET @sql = CONCAT('INSERT INTO PROCEDURE_LOG VALUES (', QUOTE(PROCEDURE_NAME), ',', QUOTE(SQL_TEXT), ', null)'); PREPARE stmt FROM @sql; EXECUTE stmt; END // delimiter ;

  • MySQL
  • 回答数1
  • ありがとう数12

質問者が選んだベストアンサー

  • ベストアンサー
  • mpro-gram
  • ベストアンサー率74% (170/228)
回答No.1

stored function からは procedure 経由でも prepared 文は発行できないようです。function自体がprepared に近い機構で動作してて多重prepareは出来ないんだとかいう理由だったような?細かい理由は英文マニュアル参照。 とりあえず、日本語マニュアルには、一文ですまされてますが。 http://dev.mysql.com/doc/refman/5.1-olh/ja/sql-syntax-prepared-statements.html 後半に以下の一文 「準備済みステートメントの SQL 構文はストアドプロシージャー内で利用できますが、ストアドファンクションやトリガー内では利用できません。」 procedure 側へ、データ取りだしSQL文も渡して、procedure内で完結させるしかないのでは? procedure の連鎖は可能なんだし。 それとも、以下の記事のように、 Gearman MySQL UDF をインストールしたうえでさらに、別アプリケーションから実行とか? http://d.hatena.ne.jp/heavenshell/20100610/1276161261 上記は、自前MySQLサーバーでないと無理かと思うけど、どういう状況における何のログなのかによっても、取り得る方法は変わってくるでしょう。

Kamen_Ride
質問者

お礼

ご回答ありがとうございます。 既存環境の障害で異常終了をすることが判明し、 原因を探るため、ストアドファンクション内でのログ出力を考えていました。 異常終了の問題となった箇所は、phpからsql文を発行し、 ストアドファンクションを呼び出している処理でした。 ご教示の通り、多重prepared はできないため、この方法は諦めました。 問題については、 ある条件の場合のみ落ちることが解っていたため、 コードの解析により解決しました。 原因は未初期化変数の参照によるものでした。 >http://d.hatena.ne.jp/heavenshell/20100610/1276161261 自前の環境でないので、 どうしようもない状況の最後の切り札として提案しようと思います。

関連するQ&A

  • MySQLのストアドプロシージャについて

    MySQL5.6のストアドプロシージャが返すSELECT結果のフェッチ方法について教えてください。 delimiter $ create procedure sample_proc() begin select * from TEST_TBL; end$ の様なストアドプロシージャがあり、これを他のストアドプロシージャから呼び出して、 ループしながらフェッチしたいのですが、どうすればよいでしょうか。

  • ストアドプロシージャについて

    Access2003とSQL Server2005Expressです。 初歩的な質問で恐縮です。 以下のストアドプロシージャのデータ取得先を、テーブルではなく 別のストアドプロシージャにしたいのですが、 その方法がわかりません。 CREATE PROCEDURE テスト AS SELECT コード, 社名, 住所, 電話 FROM 名簿     ↑     これをテーブルではなく、別のストアドプロシージャを     指定したのですが・・・。     ここをストアドプロシージャ名にするとエラーになります。     どうすればよろしいでしょうか?

  • MYSQL ストアドプロシージャの記述方法

    MYSQLのストアドプロシージャについて分からないことがあり質問させて頂きます。 SQLのwhere句の部分を引数によって条件分で変更させたいと考えています。そこでORACLEの場合は変数にいれて最後に明示的にSQLを発行して いたので可能だったのですが、MYSQLの場合はどういった記述になる のかわかりません。やりたいことは下記のような感じです。 ORACLEの場合は procedure prctest(pc out refcur,a in varchar2,b in varchar2) is sqldata varchar2(1000); whereinfo varchar2(1000); begin sqldata := 'select ID , NAME from testTbl '; if (a IS NOT NULL) then   whereinfo := whereinfo || ' acol = a ' ; end if; if (b IS NOT NULL) then   if (whereinfo IS NOT NULL) then  whereinfo := whereinfo || ' and ';   end if;   whereinfo := whereinfo || ' acol = b ' ; end if; if (whereinfo IS NOT NULL) then  sqldata := sqldata || ' where ' || whereinfo ; end if; open pc for sqldata; (ここでSQLが入ったSQLを発行) end prctest; (抜粋) ストアドをあまり使用したことがなく良い説明ではないかも しれませんが、アドバイスの方頂けたらと思います。 よろしくお願いします。

  • ストアドプロシージャの実行で...

    Test_Pro、というストアドプロシージャを実行させたいんですが、 Microsoft OLE DB Provider for SQL Server エラー '80040e14' ストアド プロシージャ 'Test_Pro' が見つかりませんでした。 というエラーが出てしまいます。どうして??? 実行させる為に書いたソースは、 set cmd = Server.CreateObject("ADODB.command") Set cmd.ActiveConnection = conn cmd.CommandText = "Test_Pro" cmd.CommandType = 4 Set rs = cmd.Execute("@a", a) です。

  • MySQL5.0のストアドプロシージャで引数の使い方がわからなくて困っています。

    MySQL5.0のストアドプロシージャで引数の使い方がわからなくて困っています。 ストアドプロシージャで IF文で引数の空の判定と、 LIKE '%name%'にその引数を使いたいのです。 どなたかわかるかたいらっしゃいませんか? □プログラムからコールする strSQL = "CALL buttonaction_proc2(syohinCd, syohinCdLast, name, count) "; □ストアドプロージャ delimiter // CREATE PROCEDURE buttonaction_proc2(IN syohinCd INT(8), IN syohinCdLast INT(8), IN name VARCHAR(40), IN count INT(8)) IF ((syihinCd IS NOT NULL) OR (syohinCdLast IS NOT NULL) OR (name IS NOT NULL)) THEN AND (SYOHIN_CD BETWEEN syohinCd AND syohinCdLast) ELSE (IF syohinCd IS NOT NULL) THEN AND (SYOHIN_CD BETWEEN syohinCd AND count) ELSE IF (syohinCdLast IS NOT NULL) THEN ( AND (SYOHIN_CD BETWEEN 1 AND syohinCdLast) ) IF (name IS NOT NULL) THEN AND NAME LIKE '%name%' END IF END IF ORDER BY SYOHIN_CD; END //

  • ストアドプロシージャ作成時のエラーについて

    お世話になっております。 CREATE PROCEDURE AAA (IN param INT) BEGIN SELECT CD, NAME FROM TBL WHERE TBL_KEY = param; END INTEGER型の引数を渡してVARCHAR型のCD、NAMEを取り出す程度のストアドプロシージャを作成しようとすると 1303 - Can't create a PROCEDURE from within another stored routine. なるエラーが表示されて作成ができません。 このエラーの理由についてコメント頂ければ幸いです。

    • ベストアンサー
    • MySQL
  • ストアドプロシージャについて

    お世話になります。 SQLServseのストアドプロシージャで、あるテーブルのテストデータを100件ほど作成したいと思っています。 しかし、プロシージャを実行すると「プライマリキーが重複しています」とエラーが出ます。 テーブル内にはすでにCODE='0001'と'0101'の2件が存在します。そのため挿入開始コードは'0002'としたのですが・・・。まだ同じエラーが発生します。 テーブル名:MST_USER  CODE char(4) ←キー  KBN  char(2)  NAME varchar(40)  PASS varchar(10) 作成したプロシージャ CREATE PROCEDURE dbo.test_update_USER AS declare @count int declare @kbn int set @count = 2 set @kbn = 0 while 1 = 1 begin update MST_USER set CODE = right('0000' + ltrim(str@count)), 4), KBN = right('00' + ltrim(str(@kbn)), 2), NAME = 'test' + ltrim(str(@count)), PASS = 'test' + ltrim(str(@count)) set @count = @count + 1 if (@count > 100) break if (@kbn > 3) set @kbn = 0 else set @kbn = @kbn + 1 end GO 何か間違えているのか自分ではわからなくなっている状態です。 どなたかご指摘いただけると幸いです。

  • ストアドプロシージャについて

    アドバイスを頂けたらと思います。 php   5.1.6 mysql   5.0.22 接続方法 PDO PHPよりストアドプロシージャを実行するとEXCUTEの部分で応答がなくなりMYSQLの SHOW PROCESSLIST を確認するとそのプロセスがSleep になってしまっています。 記述方法が間違っているか、またはどこか設定するのか、参考意見を 頂ければと思います。 PHP側 <?php try { $user = 'sys'; $pass = 'sys'; $dbh = new PDO('mysql:host=localhost;dbname=testDB', $user, $pass); if ($st = $dbh->prepare("CALL Listget()") ){ $st->execute(); while ($row = $st->fetch()) { print_r ($row); } } } catch (PDOException $e) { print 'Error: ' . $e->getMessage(). "\n"; } $dbh = null; ?> ストアド delimiter // CREATE PROCEDURE Listget ( ) BEGIN SELECT id FROM testTbl; END // よろしくお願いします。

    • ベストアンサー
    • PHP
  • ストアドプロシージャのbegin、end

    下記の様なストアドプロシージャを作成し、VB側から実行させています。 どうしても、★SQL文2★の後のreturn文を実行してくれません。 (VB側ではreturn値が0と判断します。) このreturn文を★SQL文2★の前に移動すると、return値が-1として正常に取得できます。 begin、endのブロックの記述に何か間違いがあるのでしょうか? 環境:sqlserver2000,windows2000,vb6 よろしくお願いします。 CREATE PROCEDURE [sp_AAA] @PARAM1 varchar(16) AS begin if (~) begin ★SQL文1★ if (@@ERROR <> 0) begin return @@ERROR end end ★SQL文2★ return -1 ←ココ end

  • postgres ストアドファンクションないのレコードの取得について

    質問させていただきます pg/plsqlのストアドファンクション内で 受け取った引数を sql := select * from hoge; FOR rec IN EXECUTE sql LOOP return rec.col;     <<<この部分で END LOOP; return; rec.引数名のようにして 引数から取得した 列を指定したいのですが、そのまま入れると そのような列はありませんと言うような返事を 返されてしまいます。 うまくやる方法はないものでしょうか? よろしくお願いします。