【问题标题】:Get the auto id for inserted row into Redshift table using psycopg2 in Python在 Python 中使用 psycopg2 将插入行的自动 ID 获取到 Redshift 表中
【发布时间】:2017-08-31 14:05:36
【问题描述】:

我正在使用 psycopg2 库从 Python 2.7 将记录插入到 Amazon Redshift 表中,并且我想恢复自动生成插入行的主 ID。

我已经尝试了可以​​在此处或使用 google 搜索在其他网站上找到的常用方法,例如:

conn=psycopg2.connect(conn_str)
conn.autocommit = True

sql = "INSERT INTO schema.table (col1, col2) VALUES (%s, %s) RETURNING id;"

cur = conn.cursor()
cur.execute(sql,(val1,val2))
id = cur.fetchone()[0]

我在 cur.execute 行收到错误:

ProgrammingError: syntax error at or near "RETURNING"

有人知道如何解决这个问题或完成同样的事情吗?

我必须在我的代码中使用 psycopg2

【问题讨论】:

    标签: python python-2.7 amazon-web-services amazon-redshift psycopg2


    【解决方案1】:

    假设您没有(可能)插入重复项,您可以使用 python 执行此操作。我假设您提供的代码处于循环中;循环的细节无关紧要,但将# before the loop 部分放在循环之前。

    # before the loop
    # you probably have a list or dict of values that you're inputting. Re-use that if you can; if you can't, create a dict
    sample_dict = {}
    # end before the loop
    
    /* existing code */
    conn=psycopg2.connect(conn_str)
    conn.autocommit = True
    
    # use this query instead of your current one (just remove the RETURNING clause)
    ins_sql = "INSERT INTO schema.table (col1, col2) VALUES (%s, %s);"
    
    # this query will get the id of those last added values
    sel_sql = "SELECT id FROM schema.table WHERE col1 = %s AND col2 = %s ORDER BY id DESC LIMIT 1;"
    
    cur = conn.cursor()
    cur.execute(ins_sql,(val1,val2))
    
    # new stuff here!
    cur.execute(sel_sql,(val1,val2))
    id = cur.fetchone()[0]
    sample_dict[val1 + '|' + val2] = id
    

    注意事项:

    1. 我还没有测试过这个确切的脚本
    2. 如果您插入重复值,这可能不起作用
    3. 您没有清理输入或使用准备好的语句(不能 100% 确定这是一个选项,TBH)
    4. 您比我更了解您的数据库和代码结构;利用这些知识
    5. 这不是最有效的解决方案,但它应该满足您的需求。

    【讨论】:

      【解决方案2】:

      您可以使用以下查询从 redshift 获取最后插入的 id。

      SELECT top 1 id from sampletable where created < Getdate() order by created desc;
      

      其中“id”是您感兴趣的字段,“created”是包含日期时间信息的字段。

      使用创建的日期时间信息的原因是,如果该表用于批量插入,则可能会出现 id 为连续的记录,例如 1,33,35,56,103 等..... 在上述情况下,使用 max(id) 不会按预期工作。 因为最后插入的 id 可以是之前没有插入的任何数字。

      【讨论】:

        【解决方案3】:

        目前,Redshift 仍然不支持 RETURNING 语法,我在这里找不到满意的答案。因此,我发布了一个通用解决方案,以防万一有人需要。

        此解决方案的唯一假设是您知道您刚刚插入了多少条记录。假设 x 是插入的记录数,您可以运行以下查询:

        SELECT id 
        FROM table 
        ORDER BY id DESC
        LIMIT {x}
        

        非常重要!您必须在同一事务中与插入查询一起运行此查询。否则,它将不起作用。

        【讨论】:

          【解决方案4】:

          如果你知道如何唯一地找到没有id的行,你也可以在select中查询id。

          【讨论】:

            【解决方案5】:

            Redshift 目前无法使用,因为它不支持通过 RETURNING 语法返回最后一个插入 ID。您可能需要做的是在事务中使用SELECT MAX(id) FROM schema.table;,这可能不是您想听到的,但似乎是您在 Redshift 当前状态下可以做的最好的事情。

            【讨论】:

            • 很遗憾这不是真的。我在我的情况下尝试了 Max(id) 方法,但 redshift 不会按顺序增加标识列值..即它可以在生成的 id 之间留下空隙。新生成的 id 保证是唯一的,但不一定高于 Max(id) ,也可以低于。例如。表上的当前id可以是1,2,6,7,8并插入新记录,它可以分配3的id,它是唯一的,但不超过max(id)。
            • @ShrikantPrabhu,感谢您的指点。 This article 调查此问题。可能最简单的尝试是使用IDENTITY (1,1),但我不确定它是否有帮助。实际上,在缺乏有关新插入记录的信息的情况下,根本不确定如何使用 Redshift..
            • @MarSoft 我意识到这条评论已经过时了,但是,由于 REDSHIFT 的分片/分布式特性,使用 IDENTITY(1,1) 并没有帮助。每个节点或切片以不会重复或冲突的方式从不同的 ID 子集中分配。这意味着节点不需要相互交谈来分配身份,但这也意味着“顺序”/“按顺序”分配是保证的.
            猜你喜欢
            • 1970-01-01
            • 2011-07-11
            • 1970-01-01
            • 1970-01-01
            • 2019-05-22
            • 1970-01-01
            • 1970-01-01
            • 2012-07-26
            相关资源
            最近更新 更多