Heim  >  Fragen und Antworten  >  Hauptteil

Das Ausführen der CONCAT-Anweisung in einer gespeicherten Prozedur funktioniert nicht

<p>Ich habe zwei Tabellen, eine Basistabelle, die verschiedene Informationen über den Wert „tconst“ (auch den Primärschlüssel) enthält, und eine weitere Tabelle, die mit mehreren „tconst“-Werten von „nconst“ unter dem Namen „titleId“ verknüpft ist. </p> <p>---Basistabelle 'titlebasics'</p> <table class="s-table"> <thead> <tr> <th>tconst</th> <th>Titeltyp</th> <th>...</th> </tr> </thead> <tbody> <tr> <td>tt0000009</td> <td>Filme</td> <td>...</td> </tr> <tr> <td>tt0000147</td> <td>Filme</td> <td>...</td> </tr> <tr> <td>...</td> <td>...</td> <td>...</td> </tr> </tbody> </table> <p>---Zusätzliche Informationstabelle 'knownfortitles'</p> <table class="s-table"> <thead> <tr> <th>id</th> <th>nconst</th> <th>Titelreihenfolge</th> <th>Titel-ID</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>nm0000001</td> <td>1</td> <td>tt0050419</td> </tr> <tr> <td>2</td> <td>nm0000001</td> <td>2</td> <td>tt0053137</td> </tr> <tr> <td>...</td> <td>...</td> <td>...</td> <td>...</td> </tr> </tbody> </table> <p>Das „Problem“ besteht darin, dass einige Werte in <code>knownfortitles.titleId</code> nicht in <code>titlebasics.tconst</code> vorhanden sind. Ich möchte eine gespeicherte Prozedur erstellen, in der ich die Namen von zwei Tabellen und zwei entsprechenden Spalten als Parameter übergeben kann. Dieser Prozess prüft zunächst, ob der Wert, der in der ersten Tabelle nicht vorhanden ist, tatsächlich in der zweiten Tabelle vorhanden ist, und fügt in diesem Fall eine neue Tabelle mit dem Namen <code>is_in_<base_table_name></code> hinzu . Anschließend wird diese Spalte mit dem booleschen Wert aus jeder Zeile in der zweiten Tabelle aktualisiert. Ich möchte dies in einer gespeicherten Prozedur tun, da ich viele Tabellen mit diesem Problem habe und diese Prozedur verwenden möchte, anstatt immer wieder denselben Code mit unterschiedlichen Werten zu schreiben.Allerdings erhalte ich eine Fehlermeldung, wenn ich versuche, mein Programm aufzurufen, und ich kann es scheinbar nicht beheben. </p> <p>Da es sich um eine gespeicherte Prozedur handelt, stecke ich hier fest. </p> <pre class="brush:php;toolbar:false;">CREATE PROCEDURE `CheckValueExistsInBaseTable`( IN geprüftTabelle VARCHAR(100), IN referenziertBaseTable VARCHAR(100), IN geprüftCol VARCHAR(100), IN referiertCol VARCHAR(100) ) BEGINNEN 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); – Fügen Sie der überprüften Tabelle eine neue Spalte hinzu, falls diese nicht vorhanden ist SET @sql_statement1 = CONCAT('IF (SELECT CASE WHEN EXISTS( Wählen Sie 1 FROM ',checkedTable,' WHERE ', reviewedCol, ' NOT IN (SELECT ', referencedCol, ' FROM ', referencedBaseTable, ')) DANN 1 ELSE 0 ENDE ) = 1 DANN ALTER TABLE ', reviewedTable, ' ADD ', @new_column_name, ' BOOL; ANDERS NULL AUSWÄHLEN; ENDE WENN'); PREPARE stmt1 FROM @sql_statement1; EXECUTE stmt1; DEALLOCATE PREPARE stmt1; – Aktualisieren Sie die Spalte „is_in_referencedBaseTable“ in der überprüften Tabelle SET @sql_statement2 = CONCAT('UPDATE ', reviewedTable, ' SET ', @new_column_name, ' = CASE WHEN EXISTS(SELECT * FROM ', referencedBaseTable, ' WHERE ', referencedBaseTable, '.', referencedCol, ' = ', geprüfte Tabelle, '.', geprüfte Spalte, ') THEN 1 ELSE 0 END'); PREPARE stmt2 FROM @sql_statement2; EXECUTE stmt2; DEALLOCATE PREPARE stmt2; ENDE</pre> <p>Egal, was ich zu ändern versuche, es wird mir eine der folgenden Fehlermeldungen angezeigt. </p> <blockquote> <p>Fehlercode: 1064. Es liegt ein Fehler in Ihrer SQL-Syntax vor. Sehen Sie im Handbuch Ihrer MySQL-Serverversion nach, welche Syntax in der Nähe von „NULL“ in Zeile 1 zu verwenden ist. </blockquote> <p> oder </p> <blockquote> <p>Fehlercode: 1064. Es liegt ein Fehler in Ihrer SQL-Syntax vor. Sehen Sie im Handbuch Ihrer MySQL-Serverversion nach, wie Sie „IF (SELECT CASE WHEN EXISTS()“ verwenden. Wählen Sie 1 Aus bekannten Werken WHERE titleId NOT' in Zeile 1</p> </blockquote> <p>Ich habe auch Testprogramme erstellt, um zu überprüfen, welche Teile möglicherweise Probleme haben, aber beide funktionieren einwandfrei, was mich noch mehr verwirrt. Der erste gibt einfach das zurück, was ich in <code>CONCAT</code> eingegeben habe, um zu sehen, ob es Syntaxfehler enthält.</p> <pre class="brush:php;toolbar:false;">CREATE PROCEDURE `test`( IN geprüftTabelle VARCHAR(100), IN referenziertBaseTable VARCHAR(100), IN geprüftCol VARCHAR(100), IN referenziertCol VARCHAR(100), IN neuer_Spaltenname VARCHAR (100) ) BEGINNEN – Deklarieren der Variablen und Zuweisen des Werts deklariere 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 (SELECT CASE WHEN EXISTS( Seite 1 FROM ',checkedTable,' WHERE ', reviewedCol, ' NOT IN (SELECT ', referencedCol, ' FROM ', referencedBaseTable, ')) DANN 1 ELSE 0 ENDE ) = 1 DANN ALTER TABLE ', reviewedTable, ' ADD ', @new_column_name, ' BOOL; ANDERS NULL AUSWÄHLEN; ENDE WENN'); – Drucken des Werts auf der Konsole SELECT concat(myvar) AS Variable; ENDE</pre> <p>此过程给出下一个结果:</p> <pre class="brush:php;toolbar:false;">IF (SELECT CASE WHEN EXISTS( Seite 1 来自知名作品 WHERE titleId NOT IN (SELECT tconst FROM titlebasics)) DANN 1 ELSE 0 ENDE ) = 1 DANN ALTER TABLE knowfortitles ADD is_in_titlebasics BOOL; ANDERS NULL AUSWÄHLEN; ENDE WENN</pre> <p>确切的代码块.</p> <pre class="brush:php;toolbar:false;">CREATE PROCEDURE `test2`() BEGINNEN IF (WÄHLEN SIE FALL, WENN EXISTIERT( Seite 1 来自知名作品 WHERE titleId NOT IN (SELECT tconst FROM titlebasics)) DANN 1 ELSE 0 ENDE ) = 1 DANN ALTER TABLE knowfortitles ADD is_in_titlebasics BOOL; ANDERS NULL AUSWÄHLEN; ENDE WENN; ENDE</pre> <p>此过程将列 <code>is_in_titlebasics</code> 添加到表 <code>knownfortitles</code> 中,这就是我想要发生的事情,所以这很好.此时,我完全迷失了,不知道为什么我的实际存储过程不起作用,因为它基本上是最后两个过程的组合.我暂时忽略了我希望存储过程执行的第二部分,因为我遇到的错误似乎将第一个 <code>CONCAT</code> 语句视为问题.</p> <p>
P粉644981029P粉644981029410 Tage vor561

Antworte allen(1)Ich werde antworten

  • P粉798343415

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

    感谢 P. Salmon,我了解到问题是通过准备好的语句运行 IF ... THEN 语句。这不可能。经过一番修改后,我想出了以下程序,它的工作原理与我想要的完全一样。我希望我可以帮助一些与我遇到类似问题的人。

    DELIMITER $$
    USE `<schema>`$$
    CREATE DEFINER=`Setupinfolab`@`%` PROCEDURE `CheckValueExistsInBaseTable`(
        IN checkedTable VARCHAR(100),
        IN referencedBaseTable VARCHAR(100),
        IN checkedCol VARCHAR(100),
        IN referencedCol VARCHAR(100)
        )
    BEGIN
        SET @checkedTable = checkedTable;
        SET @referencedBaseTable = referencedBaseTable;
        SET @checkedCol = checkedCol;
        SET @referencedCol = referencedCol;
        SET @new_column_name  = CONCAT('is_in_', referencedBaseTable);
        
        -- Check if there are indeed values in checkedCol that are not present in referencedCol
        SET @query1 = CONCAT('
            SELECT CASE WHEN EXISTS(
                SELECT 1 
                FROM ',@checkedTable,'
                WHERE ',@checkedCol,' NOT IN (SELECT ',@referencedCol,' FROM ',@referencedBaseTable,')) 
                THEN 1 ELSE 0 END 
                INTO @proceed');
            
        -- Adding the boolean column
        SET @query2 = CONCAT('
            ALTER TABLE ',@checkedTable,' ADD ',@new_column_name,' BOOL;');
        
        -- Inserting boolean values in new column according to presence in referencedCol
        SET @query3 = CONCAT('
            UPDATE ',@checkedTable,' SET ',@new_column_name,' = (
                CASE WHEN EXISTS(
                    SELECT * 
                    FROM ',@referencedBaseTable,' 
                    WHERE ',@referencedBaseTable,'.',@referencedCol,' = ',@checkedTable,'.',@checkedCol,')
                THEN true ELSE false END
                ) WHERE id<>0;');
        
        PREPARE stmt1 FROM @query1;
        EXECUTE stmt1;
        
        IF @proceed = 1
        THEN 
            PREPARE stmt2 FROM @query2;
            EXECUTE stmt2;
            PREPARE stmt3 FROM @query3;
            EXECUTE stmt3;
            SELECT CONCAT(@new_column_name,' column added to table ', @checkedTable,'.') 
                AS 'Message: Done';
            DEALLOCATE PREPARE stmt2;
            DEALLOCATE PREPARE stmt3;
        ELSE 
            SELECT 'All values are present in base table. Adding column is thus unnecessary.' 
                AS 'Message: UNNECESSARY';
        END IF;
        
        DEALLOCATE PREPARE stmt1;
    END$$
    DELIMITER ;
    ;

    但是,我想指出的是,我还没有添加 TRY ... CATCH 或任何阻止程序抛出错误的内容。这只是使其发挥作用的最低限度。

    调用过程

    CALL CheckValueExistsInBaseTable(
        'knownfortitles',
        'titlebasics',
        'titleId',
        'tconst'
        );

    返回消息确认:

    或消息警告:

    仅在第一种情况下,才会根据需要添加 TINYINT(1) 列。

    Antwort
    0
  • StornierenAntwort