Mysql 如果不存在会在存储过程中给我一个错误

Posted

技术标签:

【中文标题】Mysql 如果不存在会在存储过程中给我一个错误【英文标题】:Mysql if not exists gives my an error in a stored-procedure 【发布时间】:2019-04-24 05:07:38 【问题描述】:

我在phpmyadmin 中使用mysql 有以下存储过程:

CREATE DEFINER=`user`@`localhost` PROCEDURE `set_address`(IN `patient_street` VARCHAR(128), IN 
`patient_city` VARCHAR(45), IN `patient_post_code` VARCHAR(45), IN `patient_state_or_province` VARCHAR(45), IN `patient_country` VARCHAR(45)) 
NOT DETERMINISTIC NO SQL SQL SECURITY 
DEFINER 
BEGIN 
IF NOT EXISTS (SELECT a.address_id FROM address as a where a.street = patient_street and a.city = patient_city and a.post_code = patient_post_code and a.country = patient_country) 
THEN 
BEGIN 
INSERT INTO address (street, city, post_code, state_or_province, country) VALUES (patient_street, patient_city, patient_post_code, patient_state_or_province, patient_country); 
SELECT LAST_INSERT_ID(); 
END; 
ELSE 
BEGIN 
SELECT a.address_id FROM address as a where a.street = patient_street and a.city = patient_city and a.post_code = patient_post_code and a.country = patient_country 
END; 
END IF; 
END;

但是,IF NOT EXISTS 中有 2 个错误:

    无法识别的关键字。 (靠近如果不存在) 意外令牌。 (近())

【问题讨论】:

每个 if 都必须有 then 和 end if。您的 insert 语句也没有多大意义,您不能将 insert...values 与这样的 select 混合使用。而且 mysql 在 if end if 块中不需要 begin end 块。 @P.Salmon 我想首先检查地址是否已经存储在我的数据库中,否则存储它并获取它的相应 ID。 您可能需要终止 insert..values 语句。 @P.Salmon 我更新了我的代码。我仍然得到同样的错误。 你真的应该删除终止语句的要求——你错过了;在 end if 和所有 end 块之后,您也没有表明您在过程创建代码之前和之后重置分隔符(您也没有显示)。 【参考方案1】:

就个人而言,如果我需要编写一个执行指定操作并返回结果集的过程,我会这样写:

DELIMITER $$

CREATE DEFINER=`user`@`localhost` PROCEDURE `set_address`
(IN `patient_street`            VARCHAR(128)
,IN `patient_city`              VARCHAR(45)
,IN `patient_post_code`         VARCHAR(45)
,IN `patient_state_or_province` VARCHAR(45)
,IN `patient_country`           VARCHAR(45)
)
NOT DETERMINISTIC SQL SECURITY DEFINER
BEGIN
  DECLARE li_address_id BIGINT DEFAULT NULL;
  -- check for existing row and get address_id
  SELECT a.address_id
    INTO li_address_id
    FROM address a
   WHERE a.street    = patient_street
     AND a.city      = patient_city
     AND a.post_code = patient_post_code
     AND a.country   = patient_country
   LIMIT 1 ;
  -- if we didn't find a matching row
  IF li_address_id IS NULL THEN
    -- add a row and get the new address_id
    INSERT INTO address (street, city, post_code, state_or_province, country) VALUES
    (patient_street, patient_city, patient_post_code, patient_state_or_province, patient_country);
    SELECT LAST_INSERT_ID() INTO li_address_id;
  END IF;

  -- return address_id (either found existing row, or newly added row) as a resultset
  SELECT li_address_id AS address_id;
END$$

DELIMITER ;

如果存在一行,我们不需要运行两个SELECT 语句。我们可以检查行 AND 使用单个 SELECT 获取 address_id。

如果我们没有得到匹配的行,那么我们插入一行,并检索自动增量 id。

在任何一种情况下(找到的行或添加的行),都将 address_id 作为结果集返回。同样,我们可以使用单个 SELECT 语句而不是两个不同的语句来做到这一点。

对我来说,限制我们返回结果集的位置数量并限制我们查询数据库的次数更有意义。

【讨论】:

以上是关于Mysql 如果不存在会在存储过程中给我一个错误的主要内容,如果未能解决你的问题,请参考以下文章

在存储过程中给变量赋值的问题:

这种方法是不是总是会在 ios 中给我当天的 12:00:00?

用Navicat连接MySQL创建存储过程时提示1304错误是为啥?r并不存在呀

MySQL 存储过程参数验证

如何在课堂上设置两个外键? DJANGO ORM

MySql存储过程调用错误