【问题标题】:INSERT into table if not exists and return result如果不存在则插入到表中并返回结果
【发布时间】:2012-06-20 22:29:05
【问题描述】:

我有一个这样的'users' SQL 表结构(ID 是由于某些原因随机生成的,它不是自动递增的):

ID    name     deleted    lastActive
3242  Joe      0          20-6-2012 23:14
2234  Dave     0          20-6-2012 23:13
2342  Simon    1          20-6-2012 23:02
9432  Joe      1          20-6-2012 22:58

在一个查询中(为了避免并发查询添加两次相同的名称),我需要向表中添加一个新用户,如果还没有具有该名称的记录并且已删除 = 0。然后我需要知道结果查询(如果添加了用户),以便我可以报告是否添加了用户。这可以使用 PHP 吗?

我可以这样做(当然,作为准备好的声明!):

INSERT INTO users (ID, name) VALUES ($id, $name) 
    WHERE NOT EXISTS (SELECT 1 FROM users WHERE name = $name AND deleted = 0)

但是我怎么知道用户是否被添加?

【问题讨论】:

    标签: php mysql insert


    【解决方案1】:

    如果您使用的是 mysqli,则可以使用 mysqli_stmt_affected_rows() 函数来确定插入了多少行。

    同样,您可以使用PDOStatement::rowCount() 方法来确定为 PDO 插入了多少行。

    这两个函数都会告诉您作为查询结果插入的行数。

    【讨论】:

    • 完美,从来不知道这存在。谢谢!
    【解决方案2】:

    【讨论】:

      【解决方案3】:

      这是一个返回 ID 的不错的插入方法:

      /**
       * Execute an insert or update in the database.
       * @param $table - Table name.
       * @param $key_name - Primary key to update. NULL to a insert
       * @param $data - Column data array
       * @param $call_on_error function name that should called in case of an exception during the
       * execution of the statment, the function is expected to take one argument, the exception object
       * @return mixed An array containing the key inserted or updated on success, false on failure.
       */
      function INSERT($table, $key_name, &$data, $call_on_error = null) {
          list($min_cols, $prefix, $suffix, $key_value) = isset($data[$key_name]) ?
              array(2, 'UPDATE', " WHERE `$key_name`=:$key_name", $data[$key_name]) :
              array(1, 'INSERT', '', null);
          if (count($data) < $min_cols) {
              return false;
          }
          $set_clause = '';
          foreach ($data as $k => $v) {
              if ($k !== $key_name) {
                  if (($flag_name = strstr($k, "__", true))) {
                      if (strcmp($k, "{$flag_name}__mask") && isset($data["{$flag_name}__value"]))
                          $set_clause .= ",`$flag_name`=:{$flag_name}__value | (`$flag_name` & :{$flag_name}__mask)";
                  } else {
                      $set_clause .= ",`$k`=:$k";
                  }
              }
          }
          global $dbo_error_duplicated;
          $dbo_error_duplicated = false;
          $dbh = DBH();
          try {
              $sth = $dbh->prepare("$prefix $table SET " . substr($set_clause, 1) . $suffix);
              $res = $sth->execute($data);
          } catch (PDOException $e) {
              $dbo_error_duplicated = $sth->errorCode() === '23000';
              echo $e;
              if(isset($call_on_error)){
                  call_user_func($call_on_error, $e);
              }
              $res = false;
          }
          if ($res) {
              if ($key_value === null && is_numeric($id = $dbh->lastInsertId())) {
                  $key_value = $id;
              }
              $res = $key_value === null ? false : array($key_name => $key_value);
          }
          return $res;
      }
      

      还有……DBH 配置:

      /**
       * Get Data Base Handler.
       * Manual @ http://www.php.net/manual/en/pdostatement.fetch.php
       * More info @ http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/
       *
       * @return PDO Data Base Handler
       */
      function DBH() {
          global $DBH;
          global $db_config;
      
          if ($DBH === null) {
              // throws PDOException on connection error
              $DBH = new PDO("mysql:host=$db_config[host];dbname=$db_config[dbname]", $db_config['user'], $db_config['pass'],
                              array(PDO::ATTR_PERSISTENT => $db_config['persistent'], PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES '$db_config[encoding]'"));
              // ask PDO to throw exceptions for any error
              $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
          }
          return $DBH;
      }
      

      使用这个 .ini 文件:

      [db_config]
      persistent  = true
      host        = "localhost"
      user        = "root"
      pass        = ""
      dbname      = "theDbName"
      # host      = "db.production_host.com"
      # user      = "prod_root"
      # pass      = "big4nd5tr0ngp4s5word"
      # dbname    = "theDbName"
      encoding    = "UTF8"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-14
        • 2018-09-17
        相关资源
        最近更新 更多