検索

ホームページ  >  に質問  >  本文

ストアド プロシージャでの CONCAT ステートメントの実行が機能しない

<p>2 つのテーブルがあります。1 つは値 'tconst' (主キー) に関するさまざまな情報を含むベース テーブル、もう 1 つは 'titleId' という名前で 'nconst' からの複数の 'tconst' 値にリンクされているテーブルです。 </p> <p>---ベース テーブル 'titlebasics'</p> <テーブルクラス="s-テーブル"> <頭> <tr> <th>tconst</th> <th>タイトルタイプ</th> <th>...</th> </tr> </頭> <みんな> <tr> <td>tt0000009</td> <td>映画</td> <td>...</td> </tr> <tr> <td>tt0000147</td> <td>映画</td> <td>...</td> </tr> <tr> <td>...</td> <td>...</td> <td>...</td> </tr> </tbody> </テーブル> <p>---追加情報テーブル 'knownfortitles'</p> <テーブルクラス="s-テーブル"> <頭> <tr> id <th>nconst</th> <th>タイトル順</th> タイトルID </tr> </頭> <みんな> <tr> 1 <td>nm0000001</td> 1 <td>tt0050419</td> </tr> <tr> 2 <td>nm0000001</td> 2 <td>tt0053137</td> </tr> <tr> <td>...</td> <td>...</td> <td>...</td> <td>...</td> </tr> </tbody> </テーブル> <p>「問題」は、<code>knownfortitles.titleId</code> の一部の値が <code>titlebasics.tconst</code> に存在しないことです。 2 つのテーブルと 2 つの対応する列の名前をパラメーターとして渡すことができるストアド プロシージャを作成したいと考えています。このプロセスでは、まず、最初のテーブルに存在しない値が実際に 2 番目のテーブルに存在するかどうかを確認し、存在する場合は、<code>is_in_<base_table_name></code> という値を 2 番目のテーブルに追加します。リスト。その後、2 番目のテーブルの各行のブール値でこの列を更新します。この問題を抱えたテーブルがたくさんあり、異なる値を使用して同じコードを何度も記述するのではなく、このプロシージャを使用できるようにしたいため、これをストアド プロシージャで実行したいと考えています。しかし、プログラムを呼び出そうとするとエラーが発生し、修正できないようです。 </p> <p>ストアド プロシージャとしては、ここで行き詰まってしまいます。</p> <pre class="brush:php;toolbar:false;">CREATE PROCEDURE `CheckValueExistsInBaseTable`( INcheckedTable VARCHAR(100)、 IN 参照ベーステーブル VARCHAR(100)、 IN selectedCol VARCHAR(100)、 IN 参照列 VARCHAR(100) ) 始める DECLARE new_column_name VARCHAR(100) DEFAULT 'is_in_baseTable'; DECLARE sql_statement1 VARCHAR(1000) DEFAULT 'SELECT NULL;'; DECLARE sql_statement2 VARCHAR(1000) DEFAULT 'SELECT NULL;'; SET @new_column_name = CONCAT('is_in_',referencedBaseTable); -- チェックされたテーブルに新しい列が存在しない場合は追加します。 SET @sql_statement1 = CONCAT('IF (SELECT CASE WHEN EXISTS( 選択1 FROM '、checkedTable、' WHERE '、checkedCol、' NOT IN (SELECT '、referencedCol、' FROM '、referencedBaseTable、')) THEN 1 ELSE 0 終了 ) = 1 それから ALTER TABLE '、checkedTable、' ADD '、@new_column_name、' BOOL; それ以外 NULL を選択します。 END IF'); @sql_statement1 から stmt1 を準備します。 stmt1 を実行します。 DEALLOCATE PREPARE stmt1; -- チェックされたテーブルの is_in_referencedBaseTable 列を更新します SET @sql_statement2 = CONCAT('UPDATE ',checkedTable,'SET', @new_column_name, ' = CASE WHEN EXISTS(SELECT * FROM ', ReferencedBaseTable、' WHERE '、referencedBaseTable、'.'、 ReferencedCol、' = '、checkedTable、'.'、checkedCol、') THEN 1 ELSE 0 END'); @sql_statement2 から stmt2 を準備します。 stmt2 を実行します。 DEALLOCATE PREPARE stmt2; END</pre> <p>これ以上の変更は認められません、この都市は私たちの以下の説明の一つです。</p> <ブロック引用> <p> 不正な SQL 手続きコード: 1064。 不正な SQL 手続きメソッドには不正な手続きがあります。不正な MySQL サーバー バージョンに対応する操作を確認し、最初の行「NULL」付近で使用される正しい手続きメソッドを確認してください。</p> </blockquote> <p>または</p> <ブロック引用> <p> セキュリティコード: 1064。 問題のある SQL メソッドには問題があります。 問題のある MySQL サーバーのバージョンに対応する処理を検出し、 'IF (SELECT CASE WHEN EXISTS() 選択1 来自知名作品 WHERE titleId NOT' が最初の行にあります</p> </blockquote> <p>私たちは、問題が発生する可能性のある部分を検査するためのプログラムも作成しましたが、両方ともうまく機能したため、さらに慎重になりました。中に入力されたコンテンツを調べて、そこに何らかの法的制限が存在するかどうかを確認します。</p> <pre class="brush:php;toolbar:false;">CREATE PROCEDURE `test`( INcheckedTable VARCHAR(100)、 IN 参照ベーステーブル VARCHAR(100)、 IN selectedCol VARCHAR(100)、 IN 参照列 VARCHAR(100)、 IN 新しい列名 VARCHAR (100) ) 始める -- 変数の宣言と値の代入 myvar VARCHAR(1000) を宣言します。 DECLARE new_column_name VARCHAR(100) DEFAULT 'is_in_baseTable'; SET @new_column_name = CONCAT('is_in_',referencedBaseTable); SET myvar = CONCAT('IF (存在する場合はケースを選択( 選択1 FROM '、checkedTable、' WHERE '、checkedCol、' NOT IN (SELECT '、referencedCol、' FROM '、referencedBaseTable、')) THEN 1 ELSE 0 終了 ) = 1 それから ALTER TABLE '、checkedTable、' ADD '、@new_column_name、' BOOL; それ以外 NULL を選択します。 END IF'); -- コンソールへの値の出力 SELECT concat(myvar) AS 変数; END</pre> <p>この过程次の結果:</p> <pre class="brush:php;toolbar:false;">IF (存在する場合は SELECT CASE( 選択1 来自知名作品 WHERE titleId が入っていない (titlebasics から tconst を選択)) THEN 1 ELSE 0 終了 ) = 1 それから ALTER TABLE knownfortitles ADD is_in_titlebasics BOOL; それ以外 NULL を選択します。 END IF</pre> <p>この段階のコードは明らかですが、これは次の 2 番目の手順を使用したためであることがわかります。この手順では、この厳密なコードが使用されています。 <pre class="brush:php;toolbar:false;">CREATE PROCEDURE `test2`() 始める IF (存在する場合はケースを選択( 選択1 来自知名作品 WHERE titleId が入っていない (titlebasics から tconst を選択)) THEN 1 ELSE 0 終了 ) = 1 それから ALTER TABLE knownfortitles ADD is_in_titlebasics BOOL; それ以外 NULL を選択します。 終了 IF; END</pre> <p>この过程将列 <code>is_in_titlebasics</code>表 <code>knownfortitles</code> に追加しました。このとき、私は完全に迷ってしまい、結局のところ、最後の 2 つのプロセスの組み合わせであるため、自分の実際の保存プロセスが機能しないとは知りませんでした。忽略了我希望存您進行行的第 2 部分,因為我遇得错误幎最初の <code>CONCAT</code> </p> この句は問題です。 <p>この問題が頻繁に起こることを望んでいますが、私たちは単に抜粋しただけです。
P粉644981029P粉644981029480日前623

全員に返信(1)返信します

  • P粉798343415

    P粉7983434152023-09-07 00:02:02

    P. Salmon のおかげで、プリペアド ステートメントを介して IF ... THEN ステートメントを実行することが問題であることが分かりました。不可能だよ。いくつかいじくり回した結果、希望どおりに動作する次のプログラムを思いつきました。私と同じような問題を抱えている人たちを助けることができれば幸いです。

    リーリー

    ただし、プログラムがエラーをスローしないようにするために TRY ... CATCH などを追加していないことを指摘しておきます。これは、機能させるための最低限のものです。

    呼び出しプロセス

    リーリー

    返信メッセージの確認:

    またはメッセージ警告:

    最初のケースの場合のみ、TINYINT(1) 列が必要に応じて追加されます。

    返事
    0
  • キャンセル返事