【问题标题】:Making a union of views in MySQL Stored Procedure在 MySQL 存储过程中合并视图
【发布时间】:2018-11-17 07:19:04
【问题描述】:

我正在创建一个 MySQL 存储过程,它接收两个视图的名称,并在它们上执行联合到两个视图中的第一个。

我使用准备好的语句将视图名称作为字符串,因此我可以将此存储过程与大量其他存储过程一起使用,这些存储过程会生成不同名称的视图。

以下代码按预期工作:

DROP view if exists test1;
DROP view if exists test2;

CREATE VIEW test1 as SELECT "Cows";
CREATE VIEW test2 as SELECT "Horses";

DROP VIEW if exists tempView;
CREATE VIEW tempView AS SELECT * FROM test1 UNION SELECT * FROM test2;
SELECT * from tempView;

但是,当我执行以下代码时:

DELIMITER //
DROP PROCEDURE IF EXISTS SP_unionViews //
CREATE PROCEDURE SP_unionViews(IN viewname varchar(255), 
                               IN viewname2 varchar(255))
BEGIN
    DROP VIEW IF EXISTS tempView;
    SET @in1 = viewname;
    SET @in2 = viewname2;
    SET @str = 'CREATE VIEW tempView AS 
       SELECT * FROM ? UNION SELECT * FROM ?';
    PREPARE stmt FROM @str;
    EXECUTE stmt USING @in1, @in2;

    SET @str2 = 'DROP VIEW ?';
    SET @in3 = viewname;
    PREPARE stmt2 FROM @str2;
    EXECUTE stmt2 USING @in3;

    SET @str3 = 'CREATE VIEW ? AS SELECT * FROM tempView';
    PREPARE stmt3 FROM @str3;
    EXECUTE stmt3 USING @in3;

    DEALLOCATE PREPARE stmt;
    DEALLOCATE PREPARE stmt2;
    DEALLOCATE PREPARE stmt3;
END //
DELIMITER ;

DROP view if exists test1;
DROP view if exists test2;

CREATE VIEW test1 as SELECT "Cows";
CREATE VIEW test2 as SELECT "Horses";
CALL SP_unionViews(test1, test2);
SELECT * from test1;

我收到以下错误:

#1054 - Unknown column 'test1' in 'field list'

这似乎表明此存储过程正在尝试将 test1 作为列使用它不应该是一个的地方。但我不知道在哪里。

更新: 如下编辑时,我希望解决方案能够工作,但它给了我另一个错误。

新代码如下:

DELIMITER //
DROP PROCEDURE IF EXISTS SP_unionViews //
CREATE PROCEDURE SP_unionViews(IN viewname varchar(255), 
                               IN viewname2 varchar(255))
BEGIN
    DROP VIEW IF EXISTS tempView;
    SET @str = CONCAT('
    CREATE VIEW tempView AS 
        SELECT * FROM ', viewname, ' UNION SELECT * FROM ', viewname2);
    PREPARE stmt FROM @str;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

    SET @str2 = CONCAT('DROP VIEW ', viewname, ';');
    PREPARE stmt2 FROM @str2;
    EXECUTE stmt2;
    DEALLOCATE PREPARE stmt2;

    SET @str3 = CONCAT('CREATE VIEW ', viewname ,' AS SELECT * FROM tempView');
    PREPARE stmt3 FROM @str3;
    EXECUTE stmt3;
    DEALLOCATE PREPARE stmt3;
END //
DELIMITER ;

DROP view if exists test1;
DROP view if exists test2;

CREATE VIEW test1 as SELECT "Cows";
CREATE VIEW test2 as SELECT "Horses";
CALL SP_unionViews("test1", "test2");
SELECT * from test1;

它的错误是:

#1615 - Prepared statement needs to be re-prepared

【问题讨论】:

  • 顺便说一句,请不要担心“选择 *”的东西。这是样板文件。
  • 编辑修复:“test1”、“test2”需要是字符串文字。
  • 还进行了编辑以修复:创建视图不喜欢子查询。

标签: mysql stored-procedures prepared-statement union sql-view


【解决方案1】:

您不能在准备好的语句中使用表名参数,因此您需要在准备语句之前将表名放入查询字符串中。尝试将您的查询更改为:

SET @str = CONCAT('
CREATE VIEW tempView AS 
    SELECT * FROM (
        SELECT * FROM ', viewname, ' UNION SELECT * FROM ', viewname2, '
    )');

SET @str2 = CONCAT('DROP VIEW ', viewname);

SET @str3 = CONCAT('CREATE VIEW ', viewname, ' AS SELECT * FROM tempView');

完成此操作后,您将不再需要 EXECUTEs 的任何参数

【讨论】:

  • 那么准备好的语句中的参数是否仅对列和比较值有用?
  • 哦,我明白了。这是一个“什么?”的问题。可以。
  • @Feygon 它们基本上只能用于数据文字。
  • @Feygon 对丢失的)s 感到抱歉,我已经编辑了答案。
  • 新错误。我真的认为你的解决方案会奏效。
猜你喜欢
  • 2010-10-15
  • 2014-09-23
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-03
  • 1970-01-01
相关资源
最近更新 更多