【问题标题】:mysql_insert_id alternative for postgresqlmysql_insert_id 替代 postgresql
【发布时间】:2010-09-08 12:43:03
【问题描述】:

对于 PostgreSQL,mysql_insert_id() php 函数是否有替代方法?大多数框架通过查找 ID 中使用的序列的当前值来部分解决问题。但是,有时主键不是串行列....

【问题讨论】:

    标签: php postgresql insert-id


    【解决方案1】:

    从 PostgreSQL 的角度来看,在伪代码中:

     * $insert_id = INSERT...RETURNING foo_id;-- only works for PostgreSQL >= 8.2. 
    
     * INSERT...; $insert_id = SELECT lastval(); -- works for PostgreSQL >= 8.1
    
     * $insert_id = SELECT nextval('foo_seq'); INSERT INTO table (foo...) values ($insert_id...) for older PostgreSQL (and newer PostgreSQL)
    

    pg_last_oid() 仅适用于您有 OID 的情况。自 PostgreSQL 8.1 起,OID 已默认关闭。

    因此,根据您拥有的 PostgreSQL 版本,您应该选择上述方法之一。当然,理想情况下,使用抽象出上述内容的数据库抽象库。否则,在低级代码中,它看起来像:

    方法一:插入...返回

    // yes, we're not using pg_insert()
    $result = pg_query($db, "INSERT INTO foo (bar) VALUES (123) RETURNING foo_id");
    $insert_row = pg_fetch_row($result);
    $insert_id = $insert_row[0];
    

    方法二:INSERT; lastval()

    $result = pg_execute($db, "INSERT INTO foo (bar) values (123);");
    $insert_query = pg_query("SELECT lastval();");
    $insert_row = pg_fetch_row($insert_query);
    $insert_id = $insert_row[0];
    

    方法三:nextval();插入

    $insert_query = pg_query($db, "SELECT nextval('foo_seq');");
    $insert_row = pg_fetch_row($insert_query);
    $insert_id = $insert_row[0];
    $result = pg_execute($db, "INSERT INTO foo (foo_id, bar) VALUES ($insert_id, 123);");
    

    最安全的选择是第三种方法,但它很笨拙。最干净的是第一个,但您需要运行最新的 PostgreSQL。不过,大多数 db 抽象库还没有使用第一种方法。

    【讨论】:

    • 很好的答案,出于速度原因,我从第三种方法切换到第一种方法。我正在使用 python 和 psycopg2 并且只执行一个用于批量数据插入的语句只是一种更快的方法。想知道第三个是否真的比第一个更安全?我认为第一个和第三个同样安全,第二个有竞争条件。
    【解决方案2】:

    查看 RETURNING optional clause 以获取 INSERT 语句。 (链接到官方 PostgreSQL 文档)

    但基本上,你会这样做:

    INSERT INTO table (col1, col2) VALUES (1, 2) RETURNING pkey_col
    

    INSERT 语句本身返回受影响行的 id(或您指定的任何表达式)。

    【讨论】:

      【解决方案3】:

      来自 php.net:

      $res=pg_query("SELECT nextval('foo_key_seq') as key");
      $row=pg_fetch_array($res, 0);
      $key=$row['key'];
      // now we have the serial value in $key, let's do the insert
      pg_query("INSERT INTO foo (key, foo) VALUES ($key, 'blah blah')");
      

      这应该始终提供唯一的密钥,因为从数据库中检索到的密钥将永远不会再次检索。

      【讨论】:

        【解决方案4】:

        你也可以使用:

        $result = pg_query($db, "INSERT INTO foo (bar) VALUES (123) RETURNING foo_id");
        $insert_row = pg_fetch_result($result, 0, 'foo_id');
        

        你必须在 pg_fetch_result 中指定你要查找的行号和字段的名称,这是获取你需要的数据的更精确的方法,但我不知道这是否有一些查询性能的损失。请记住,此方法适用于 PostgreSQL 版本 8.2 及更高版本。

        【讨论】:

        • 是的,@angch 的回答中已经提到了。请注意,这不适用于其他 sql 方言(sql-server、mysql 等)
        猜你喜欢
        • 2010-09-22
        • 1970-01-01
        • 2011-02-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-24
        相关资源
        最近更新 更多