【问题标题】:Run a query in a MySQL stored procedure if a condition is true如果条件为真,则在 MySQL 存储过程中运行查询
【发布时间】:2012-04-08 08:46:20
【问题描述】:

我正在使用 MySQL 数据库并尝试创建存储过程。我怎样才能做到这一点,如果 query1 的结果没有记录,那么它会执行不同的查询?

这是我目前所拥有的:

/* CREATE DB */
CREATE DATABASE mydata;
use mydata;
/* TABLE */
CREATE TABLE mydata (
ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name                        VARCHAR(255) NOT NULL,
Value                       VARCHAR(255) NOT NULL
) ENGINE=InnoDB;
INSERT INTO mydata (Name, Value) VALUES ("testname", "testvalue");

/* STORED PROCEDURE */
delimiter //
CREATE PROCEDURE myproc(IN myTable VARCHAR(255), 
                        IN myValue VARCHAR(255), 
                        IN myValueTwo VARCHAR(255))
BEGIN
    SET @iTable=myTable;
    SET @iValue=myValue;
    SET @iValueTwo=myValueTwo;

    SET @query = CONCAT('SELECT Name FROM ', @iTable, 
        ' WHERE Value="', @iValue, '"');
    SET @querytwo = CONCAT('SELECT Name FROM ', @iTable, 
        ' WHERE Value="', @iValueTwo, '"');
    PREPARE QUERY FROM @query;
    EXECUTE QUERY;

END //
delimiter ;

/* CALL */
call myproc("mydata", "testvalue", "");

我想运行一个查询,并且仅当第一个查询没有行时才执行第二个查询。最好的方法是什么?

【问题讨论】:

  • 是否要求表和插入语句应该是动态的?使用动态 sql 不是好办法。

标签: mysql sql database


【解决方案1】:

这需要一些工作,但我做了足够的调整。您的代码问题与您的逻辑无关,而是与 MySQL 存储过程语言本身有关。在执行动态 SQL 时,它存在范围问题。

我所做的是创建一个临时表并将返回的值存放在其中

这是加载的一些示例数据

mysql> drop database if exists user391986;
Query OK, 1 row affected (0.08 sec)

mysql> create database user391986;
Query OK, 1 row affected (0.00 sec)

mysql> use user391986
Database changed
mysql> CREATE TABLE mytable (
    -> ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> Name VARCHAR(255) NOT NULL,
    -> Value VARCHAR(255) NOT NULL
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.11 sec)

mysql> INSERT INTO mytable (Name,Value) VALUES
    -> ('rolando','edge'),('pamela','washington'),
    -> ('dominique','wilkins'),('diamond','cutter');
Query OK, 4 rows affected (0.06 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT * from mytable;
+----+-----------+------------+
| ID | Name      | Value      |
+----+-----------+------------+
|  1 | rolando   | edge       |
|  2 | pamela    | washington |
|  3 | dominique | wilkins    |
|  4 | diamond   | cutter     |
+----+-----------+------------+
4 rows in set (0.00 sec)

mysql>

这里是为捕获临时表中的返回值而调整的存储过程

mysql> delimiter //
mysql> CREATE PROCEDURE myproc(IN myTable VARCHAR(255), IN myValue VARCHAR(255), IN myValueTwo VARCHAR(255))
    -> BEGIN
    ->     DECLARE foundcount INT;
    ->     DECLARE retval VARCHAR(255);
    ->
    ->     SET @iTable=myTable;
    ->     SET @iValue=myValue;
    ->     SET @iValueTwo=myValueTwo;
    ->
    ->     CREATE TEMPORARY TABLE IF NOT EXISTS mynumber (rv VARCHAR(255)) ENGINE=MEMORY;
    ->     DELETE FROM mynumber;
    ->
    ->     SET retval = 'nothing retrieved';
    ->     SET @query = CONCAT('INSERT INTO mynumber SELECT Name FROM ', @iTable, ' WHERE Value=''', @iValue, '''');
    ->     PREPARE QUERY FROM @query;
    ->     EXECUTE QUERY;
    ->     DEALLOCATE PREPARE QUERY;
    ->     SELECT COUNT(1) INTO foundcount FROM mynumber;
    ->     IF foundcount = 0 THEN
    ->         SET @querytwo = CONCAT('INSERT INTO mynumber SELECT Name FROM ', @iTable, ' WHERE Value=''', @iValueTwo, '''');
    ->         PREPARE QUERY FROM @querytwo;
    ->         EXECUTE QUERY;
    ->         DEALLOCATE PREPARE QUERY;
    ->     END IF;
    ->     SELECT COUNT(1) INTO foundcount FROM mynumber;
    ->     IF foundcount > 0 THEN
    ->         SELECT rv INTO retval FROM mynumber;
    ->     END IF;
    ->     SELECT retval;
    ->
    -> END //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql>

好的,我调用了存储过程三次。第一个什么也得不到。第二个获得第二个值。第三个得到第一个值。

mysql> CALL myproc('mytable','pamela','diamond');
+-------------------+
| retval            |
+-------------------+
| nothing retrieved |
+-------------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.02 sec)

mysql> CALL myproc('mytable','pamela','wilkins');
+-----------+
| retval    |
+-----------+
| dominique |
+-----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> CALL myproc('mytable','edge','wilkins');
+---------+
| retval  |
+---------+
| rolando |
+---------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.02 sec)

mysql>

试试看!!!

【讨论】:

  • 非常感谢罗兰多!引擎=内存;我是否必须担心最后手动删除它?每次执行后数据是否会被清除,还是我也需要处理?
  • 临时表将自行清除数据库连接是否正常断开或意外终止。
【解决方案2】:

在 mysql 中,您可以像这样使用found_rows() 内置过程:

el@apollo:~$ mysql -u root -p
Enter password: 
mysql> use your_database;
Database changed
mysql> select id from problems;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
+----+
4 rows in set (0.00 sec)

mysql> select found_rows();
+--------------+
| found_rows() |
+--------------+
|            4 |
+--------------+
1 row in set (0.00 sec)

在 mssql 中,您可以使用值 @@rowcount。然后,只有当第一个查询没有返回任何行时,您才能运行第二个查询:

EXECUTE QUERY;

IF @@rowcount = 0
BEGIN
     PREPARE QUERY FROM @querytwo;     
     EXECUTE QUERY;
END

【讨论】:

【解决方案3】:

在 Sql Server 中,您可以将结果运行到临时表中,然后检查临时表中的行,如下所示:

declare @numberResults int = 0

create table #MyTempTable(...)

insert #MyTempTable
sp_executesql Query

set @numberResults = (select count(*) from #MyTempTable)

if @numberResults = 0
 begin
  sp_executesql secondQuery
 end

【讨论】:

    【解决方案4】:

    我最简单的工作代码

    BEGIN
        IF test = 'null' THEN 
            PREPARE QUERY FROM 'SELECT username as name from login';
            EXECUTE QUERY;
        ELSE
            PREPARE QUERY FROM 'SELECT username as name2 from login';
            EXECUTE QUERY;
        END IF;
    END
    

    【讨论】:

      猜你喜欢
      • 2020-08-02
      • 2010-12-26
      • 1970-01-01
      • 1970-01-01
      • 2018-07-11
      • 2016-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多