0

現在の日付に従ってテーブル名が生成されるストアド プロシージャの下を呼び出しています。

    DELIMITER $$
USE `test`$$
DROP PROCEDURE IF EXISTS `sp_pickalertstatus`$$
CREATE PROCEDURE `sp_pickalertstatus`()
BEGIN
    DECLARE msgID  BIGINT (10);
    DECLARE tbl VARCHAR(100);
    SET msgID=(SELECT alertID FROM tbl_intofone_alert_transaction WHERE 
    deliverystatus LIKE '22%' LIMIT 1); 
    IF(msgID IS NOT NULL)THEN
        SET tbl=(SELECT CONCAT('history.tbl_',DATE_FORMAT(NOW(),"%y%m%d")));
        INSERT INTO tbl (MEMBERID,SOURCE,MOBILE,SMPPID,PRIORITY,SMSID
        ,SMSCONTENTTYPE,MESSAGE,REQUESTDATETIME,DR_GROUPID,dr_service_type,
        dr_celleb_msg_id,dr_submit_date,dr_done_date,dr_stat,dr_err,dr_smppid)
        SELECT memberid,SenderID,MSISDN,SMPPID,'1',alertID,'TXT',Message,
        updatetime,'0','PIN','0',DATE_FORMAT(InTime,'ymdHis'),
        DATE_FORMAT(updatetime,'ymdHis'),'DELIVRD',
        '000','03' FROM tbl_intofone_alert_transaction WHERE alertID=msgID;         
    END IF; 
    END$$
DELIMITER ;

「エラー コード: 1146 テーブル 'test.tbl' が存在しません」というエラーが表示されます。ここで何が間違っていますか?

Prepared ステートメントを使用してこれを行うよう提案した後、上記のコードを変更しました。

DELIMITER $$

USE `test`$$

DROP PROCEDURE IF EXISTS `sp_pickalertstatus22`$$

CREATE PROCEDURE `sp_pickalertstatus22`()
BEGIN
    DECLARE msgID  BIGINT (10);
    DECLARE tbl VARCHAR(100);
    SET msgID=(SELECT alertID FROM tbl_intofone_alert_transaction WHERE deliverystatus LIKE '22%' LIMIT 1); 
    IF(msgID IS NOT NULL)THEN
        SET tbl=(SELECT CONCAT('history.tbl_',DATE_FORMAT(NOW(),"%y%m%d")));
        SET @sl=CONCAT('INSERT INTO ?',' (MEMBERID,SOURCE,MOBILE,SMPPID,PRIORITY,SMSID,SMSCONTENTTYPE,MESSAGE,REQUESTDATETIME,
        DR_GROUPID,dr_service_type,dr_celleb_msg_id,dr_submit_date,dr_done_date,dr_stat,dr_err,dr_smppid)
            SELECT memberid,SenderID,MSISDN,SMPPID,?,alertID,?,Message,updatetime,?,?,?,DATE_FORMAT(InTime,?),
            DATE_FORMAT(updatetime,?),?,?,? FROM tbl_intofone_alert_transaction WHERE alertID=?');
        PREPARE stmt FROM @sl;
        SET @tbl=tbl;
        SET @pr='06';
        SET @txt='TXT';
        SET @grp='0';
        SET @srtyp='PIN';
        SET @clmsg='0';
        SET @intm='%y%m%d%H%i%s';
        SET @outm='%y%m%d%H%i%s';
        SET @drst='DELIVRD';
        SET @drerr='000';
        SET @drsmp='03';
        SET @msg=msgID;

        EXECUTE stmt USING @tbl,@pr,@txt,@grp,@srtyp,@clmsg,@intm,@outm,@drst,@drerr,@drsmp,@msg;       
    END IF; 
    END$$
DELIMITER ;

しかし、まだ機能していませんか?エラーが発生する

  Error Code : 1064
    You have an error in your SQL syntax; check the manual that
 corresponds to your MySQL server version for the right syntax 
to use near '? MEMBERID,SOURCE,MOBILE,SMPPID,PRIORITY,SMSID,
SMSCONTENTTYPE,MESSAGE,REQUESTDA' at line 1 

クエリ文字列を使用して準備ステートメントを実行中:

    EXECUTE stmt USING '06','TXT','0','PIN','0','%y%m%d%H%i%s'
,'%y%m%d%H%i%s','DELIVRD','000','03';

取得エラー:

Error Code : 1064
You have an error in your SQL syntax; check the manual that 
corresponds to your MySQL server version for the right syntax to 
use near ''06','TXT','0','PIN','0','%y%m%d%H%i%s','%y%m%d%H%i%s','DELIVRD',
'000','03';' at line 25
4

1 に答える 1

0

あなたの更新を考慮して、 tbl 名にプレースホルダーを使用しないでください。私が行ったように、クエリ文字列で CONCAT を使用して、構文エラー near を回避します? (?フィールド名の前に注意してください。に置き換えられていません@tbl
また、@兆候を失います。セッション変数を作成しています (セッション全体でメモリにとどまります)。これは、必要な場合にのみ役立ちます。ストアド プロシージャ内では、それらは無関係です。プロシージャが戻った後、それが使用する変数は GC できますし、GC する必要があります。

準備済みステートメントを使用します。

SET tbl=(SELECT CONCAT('history.tbl_',DATE_FORMAT(NOW(),"%y%m%d"))); -- set tbl as you normally would
PREPARE stmt FROM
CONCAT('INSERT INTO ', tbl, -- tbl is concatenated here
       ' (MEMBERID,SOURCE,MOBILE,SMPPID,PRIORITY,SMSID
        ,SMSCONTENTTYPE,MESSAGE,REQUESTDATETIME,DR_GROUPID,dr_service_type,
        dr_celleb_msg_id,dr_submit_date,dr_done_date,dr_stat,dr_err,dr_smppid)
        SELECT memberid,SenderID,MSISDN,SMPPID,?,alertID,?,Message,
        updatetime,?,?,?,DATE_FORMAT(InTime,?),
        DATE_FORMAT(updatetime,?),?,
        ?,?
        FROM tbl_intofone_alert_transaction WHERE alertID=msgID;');

EXECUTE stmt USING '1', 'TXT', '0', 'PIN', '0', 'ymdHis', 'ymdHis', 'DELIVRD','000', '03';

そのような何かがうまくいくはずです。詳細はこちら

これに対処する別の方法として、準備済みステートメントを引き続き使用して、プレースホルダーを削除することもできます。

CONCAT('INSERT INTO ', tbl,
       ' (MEMBERID,SOURCE,MOBILE,SMPPID,PRIORITY,SMSID
           ,SMSCONTENTTYPE,MESSAGE,REQUESTDATETIME,DR_GROUPID,dr_service_type,
          dr_celleb_msg_id,dr_submit_date,dr_done_date,dr_stat,dr_err,dr_smppid)
          SELECT memberid,SenderID,MSISDN,SMPPID,\'1\',alertID,\'TXT\',Message,
          updatetime,\'0\',\'PIN\',\'0\',DATE_FORMAT(InTime,\'ymdHis\'),
         DATE_FORMAT(updatetime,\'ymdHis\'),\'DELIVRD\',
        \'000\',\'03\' FROM tbl_intofone_alert_transaction WHERE alertID=msgID');

引用符をエスケープするか、二重引用符を使用して連結文字列を区切ります。ただし、形式
についてはわかりません...そうすべきではありませんか?DATE_FORMAT'%Y%d%m'

于 2013-07-05T06:52:55.580 に答える