【问题标题】:SQL = IF NOT EXISTS in a prepared statement?SQL = IF NOT EXISTS 在准备好的语句中?
【发布时间】:2014-05-27 03:02:08
【问题描述】:

我正在尝试检查我的表中是否已经存在记录,如果不存在,我想执行插入...使用准备好的语句。谁能告诉我下面有什么问题?我已经编写了带有错误检查的代码,它基本上说查询是便便:) 当涉及到 SQL 和几乎任何与编程相关的东西时,我都很糟糕,所以我真的很感激在这个看起来很狡猾的任务中分享的任何智慧......谢谢!

        $mysqli = mysqli_connect($config['host'], $config['user'], $config['pass'], $config['db']);  
        $timestamp = time();  

        $stmt = $mysqli->prepare("IF NOT EXISTS (SELECT id FROM course_licence_cart WHERE userid = ? AND courseid = ? AND lmsid = ?) BEGIN INSERT INTO course_licence_cart (lmsid, userid, courseid, assigned_by, assigned_on) VALUES (?, ?, ?, ?, ?) END");

        foreach($_POST['assignTo'] as $assignTo){
            $stmt->bind_param('iiiiiiii', $assignTo, $_POST['course'], $core['id'], $core['id'], $assignTo, $_POST['course'], $userInfo['id'], $timestamp);
            $stmt->execute();
        }

仅供参考:这是在提交表单后发生的,我检查了所有变量,它们都很好,并且过程本身运行良好(我没有IF NOT EXISTS),它只是这个新的查询类型与准备好的语句混合在一起,完全让我失望。

-- 更新--

我直接跑了以下:

IF NOT EXISTS (SELECT `id` FROM `course_licence_cart` WHERE `userid` = '175' AND `courseid` = '1' AND `lmsid` = '1') BEGIN INSERT INTO `course_licence_cart` (`lmsid`, `userid`, `courseid`, `assigned_by`) VALUES ('1', '175', '1', '175') END

我得到错误:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF NOT EXISTS (SELECT `id` FROM `course_licence_cart` WHERE `userid` = '175' AND' at line 1

【问题讨论】:

  • 你有没有直接尝试过这种说法?
  • 甚至有一个 PHP 示例作为答案之一,这个问题没有被标记
  • 对于 SQL 来说,没有像 'IF NOT EXISTS (...' 这样的测试。请参阅 'google'。无论如何,这对“数据集”没有任何意义。你知道你检查了一行。遗憾的是,数据库引擎没有。阅读您的问题 - there are NO NEW QUERY TYPES 使用'prepared queries'!这是完全相同的查询 只是一种不同的更安全的称呼方式!

标签: php sql mysqli prepared-statement exists


【解决方案1】:

首先错误的根源与准备好的语句无关。只是您不能使用 IFBEGIN ... END 块和其他超出存储例程(过程、函数、触发器、事件)范围的构造。

为了防止重复,您可以像这样利用INSERT IGNORE

$stmt = $mysqli->prepare("INSERT IGNORE INTO course_licence_cart (lmsid, userid, courseid, assigned_by, assigned_on) VALUES (?, ?, ?, ?, ?)");

foreach($_POST['assignTo'] as $assignTo){
    $stmt->bind_param('iiiiiiii', $assignTo, $_POST['course'], $core['id'], $core['id'], $assignTo, $_POST['course'], $userInfo['id'], $timestamp);
    $stmt->execute();
}

为了使它起作用,您必须定义一个唯一的约束。

CREATE UNIQUE INDEX index_name 
    ON course_licence_cart (userid, courseid, lmsid);

这里是SQLFiddle演示


现在您的代码(在更正语法之后)可以在这样的存储过程中运行

DELIMITER //
CREATE PROCEDURE add_to_cart(IN _lmsid INT, IN _userid INT, _courseid INT, IN _assigned_by INT, IN _assigned_on DATETIME)
BEGIN
    IF NOT EXISTS (SELECT *
                     FROM course_licence_cart 
                    WHERE userid = _userid 
                      AND courseid = _courseid
                      AND lmsid = _lmsid) THEN
        INSERT INTO course_licence_cart (lmsid, userid, courseid, assigned_by, assigned_on) 
        VALUES (_lmsid, _userid, _courseid, _assigned_by, _assigned_on);
    END IF;
END//
DELIMITER ;

这里是SQLFiddle演示

在这种情况下,php 代码看起来像

$stmt = $mysqli->prepare("CALL add_to_cart (?, ?, ?, ?, ?)");

foreach($_POST['assignTo'] as $assignTo){
    $stmt->bind_param('iiiiiiii', $assignTo, $_POST['course'], $core['id'], $core['id'], $assignTo, $_POST['course'], $userInfo['id'], $timestamp);
    $stmt->execute();
}

【讨论】:

  • 假设交错线程,他需要什么样的事务范围来防止在 sp 版本中插入重复项?
【解决方案2】:

由于您使用 PHP 编码,需要考虑的一件事是从该表中对 SELECT 执行 sql 查询,如果没有返回任何内容,请运行插入查询。

我确信它可以通过 SQL 完成,但我个人不知道如何。

祝你好运,如果这没有帮助,请见谅。

【讨论】:

  • ...你可以举个例子,否则这应该是一个评论。请注意,建议的方案(并且他目前正在数据库中进行试验)是不是线程安全的,并且可能需要锁定整个表(假设不能使用UNIQUE 键) - 这会杀死并发。
【解决方案3】:

在 MYSQL 中有 4 种类型的插入可用。 1)插入 2)插入忽略 3)插入重复键 4)替换

请探索它们。 据我了解,您的具体情况可以通过 INSERT IGNORE 命令处理。

注意:我在这里假设 Mysqli 与 MYSQL 相同

更新:现在我知道 mysqli 是 MYSQL 的接口。但是插入忽略的概念仍然是相同的。 了解使用 INSERT IGNORE 的示例 考虑下表。

创建表 person_tbl (first_name CHAR(20) NOT NULL, last_name CHAR(20) NOT NULL, sex CHAR(10), PRIMARY KEY (last_name, first_name));

这里名字和姓氏构成主键

现在我们运行查询

mysql> INSERT INTO person_tbl VALUES('Jay', 'Thomas');

它会在表格中添加一行

如果我们将运行上面的 sql,它将失败并出现重复记录异常。为了防止此异常,我们有 2 个选项

1)检查记录是否已经存在,如果不存在则插入记录......我们必须触发选择然后插入查询。

2) 触发 INSERT IGNORE SQL.. 它会检查表中是否存在如果记录存在则不会插入记录,如果不存在则插入记录。

例如 如果我们运行查询

mysql> INSERT IGNORE INTO person_tbl VALUES('Jay', 'Thomas');

这个sql不会插入任何记录..因为记录已经存在

但是

mysql> INSERT IGNORE INTO person_tbl VALUES('Vijay', 'Thomas');

它将在表中插入一条记录。

【讨论】:

  • 这确实应该是一条评论。如果你认为INSERT IGNORE是他需要的,举个使用中的例子。 MySQL 是 RDBMS 的一种特殊“风格”(实现),MySQLi 是 PHP 中的一组接口方法(也就是说,不,它们不是一回事——而且我不知道 MySQLi 是否只有接口使用 MySQL 或任何数据库)。
猜你喜欢
  • 2012-09-17
  • 2012-01-03
  • 1970-01-01
  • 2021-10-20
  • 2012-06-05
  • 1970-01-01
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多