如果不存在则插入表mysql问题

时间:2011-04-25 17:16:15

标签: mysql sql database

我正在尝试插入到我的表中,但前提是信息不存在。

这有效:

$sql = //"if not exists (select `id` from friends where `id` = :id) " . //ERROR!
"insert into `friends` (`id`, `fb_id`, `name`, `id2`, `fb_id2`, `name2`) " .
"values (:id, :fb_id, :name, :id2, :fb_id2, :name2)";
try 
{
  $stmt = $this->db->prepare($sql); 
  if (!$stmt)
  {
    $errorcode = (string)
    $stmt->errorCode(); 
    trigger_error("mysql errorcode : " . $errorcode, E_USER_ERROR);
    $data = array( "note" => "mysql error code: " . $errorcode );

    return json_encode( $data );    
  } 
  $stmt->bindParam(':id', $id, PDO::PARAM_INT);
  $stmt->bindParam(':fb_id', $fb_id, PDO::PARAM_INT);
  $stmt->bindParam(':name', $name, PDO::PARAM_STR);
  $stmt->bindParam(':id2', $id2, PDO::PARAM_INT); 
  $stmt->bindParam(':fb_id2', $fb_id2, PDO::PARAM_INT); 
  $stmt->bindParam(':name2', $name2, PDO::PARAM_STR); 
  $result = $stmt->execute();
  $stmt->closeCursor(); 
}       
catch (Exception $e)
{
  die ($e->getMessage() ); 
}

我在第一行中尝试了if not exists ( select id ...等,但这没有用。它使用00000返回了错误代码(string) $stmt->errorCode();,我用Google搜索它意味着:to many mysql connections,这不是问题,因为其他查询工作正常。

如何在不存在时插入表中,如何获取mysql错误信息?

4 个答案:

答案 0 :(得分:3)

我之前从未见过你的语法,在insert子句之前放置一个exists子句,但以下内容应该有效。

INSERT INTO `friends`
SELECT :id, :fp_id, :name, :id2, :fb_id2, :name2
FROM `friends`
WHERE NOT EXISTS ( select `id` from friends where `id` = :id )
LIMIT 1;

刚才意识到在此之前你的朋友桌中至少需要一条记录。

答案 1 :(得分:2)

insert IGNORE into `friends` (`id`, `fb_id`, `name`, `id2`, `fb_id2`, `name2`)
values (:id, :fb_id, :name, :id2, :fb_id2, :name2)

或者您想要防止重复的ID,您可以添加触发器

DELIMITER $$

CREATE TRIGGER bi_friends_each BEFORE INSERT ON friends FOR EACH ROW
BEGIN
  DECLARE TestId integer;

  SELECT id INTO TestId FROM friends WHERE id = new.id LIMIT 1;
  IF (id IS NOT NULL) THEN BEGIN
    /*force an error to prevent insert*/
    SELECT * FROM force_an_error_table_unwilling_to_insert_dup_key;
  END; END IF;
END $$

DELIMITER ;

请注意,如果idUNIQUEPRIMARY KEY字段,则插入重复密钥会产生错误,会回滚任何待处理的交易
如果您使用的是非事务引擎,MySQL将停止在错误点插入行,只会插入部分行。

您的问题很清楚,为什么要进行IGNORE测试。所以我会回顾一下选项和含义:

  1. 如果您希望事务失败,请将id设置为主键并正常插入,生成的冲突将生成错误并回滚事务。
  2. 如果您只想插入内容而不用担心重复ID,则设置字段为AUTOINCREMENT,并将id的值替换为null。 INSERT INTO table (id, fb_id,name,id,fb_id2,name2) VALUES ( null ,:fb_id,:name,:id2,:fb_id2,:name2)
  3. 如果您只想让一个插页不成功,请按上述INSERT IGNORE ...进行操作。
  4. 如果您没有交易(MyISAM等),您可能必须首先进行测试SELECT,并且在测试显示保存后继续进行INSERT a bunch of values

答案 2 :(得分:1)

假设您有一个唯一的id索引,您可以使用INSERT IGNORE。有关优缺点的讨论,请参阅此帖子:"INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE"

答案 3 :(得分:0)

即使您的表中没有任何行,此解决方案仍然有效。

INSERT INTO t (
    x,
    y,
    z) (
        SELECT
            '00000',
            '11111',
            '22222'
        FROM
            DUAL
        WHERE
            NOT EXISTS (
                SELECT
                    1
                FROM
                    t
                WHERE
                        c = '00000'
                    AND x = '11111'
                    AND y = '22222'
            )
        LIMIT 1
    );