【问题标题】:Python psycopg2 check row existsPython psycopg2 检查行是否存在
【发布时间】:2013-12-25 06:55:53
【问题描述】:

在 Python psycopg2 中,我如何检查一行是否存在?

def track_exists(self, track_id):
    cur = self.conn.cursor()
    cur.execute("SELECT fma_track_id FROM tracks WHERE fma_track_id = %s", (track_id,))
    if cur.fetchall() > 0:
        return true
    else:
        return false

目前我正在接受

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "mumu.py", line 38, in track_exists
if cur.fetchall() > 0:
TypeError: 'NoneType' object has no attribute '__getitem__'

【问题讨论】:

    标签: python sql postgresql psycopg2


    【解决方案1】:

    不要使用fetchall()(它返回一个永远不会“大于0”的列表),使用fetchone()

    def track_exists(self, track_id):
        cur = self.conn.cursor()
        cur.execute("SELECT fma_track_id FROM tracks WHERE fma_track_id = %s", (track_id,))
        return cur.fetchone() is not None
    

    fetchone() 返回 None 如果没有要获取的内容,并且针对 is not None 进行测试会为您提供一个方便的布尔值直接返回。

    【讨论】:

    • with fetchone() 我仍然收到return cur.fetchone() is not None TypeError: 'NoneType' object has no attribute '__getitem__'
    • 然后在您的问题中发布 full 回溯,该错误没有任何意义,听起来也不像是在这里抛出的。此代码均未使用项目访问权限。
    • 我正在使用from myModule import Database 重新加载,但没有正确重新加载。现在工作:)
    • 好。请注意,我对 fetchall() 的评论仍然有效。
    • 你也应该在这里引用 %s 吗?我读到 Postgres 会自动将所有未加引号的用户名转换为小写
    【解决方案2】:
    def track_exists(self, track_id):
        cur = self.conn.cursor()
        cur.execute("SELECT fma_track_id FROM tracks WHERE fma_track_id = %s", (track_id,))
        if len(cur.fetchall()) > 0:
            return true
        else:
            return false
    

    【讨论】:

    • 虽然您确实修复了 OP 的代码,但 3.5 年前的其他答案效率更高。因此,这不太可能对未来的读者有太大帮助。
    【解决方案3】:

    使用exists 将允许 Postgresql 在第一次出现时停止搜索,而不是搜索到用尽:

    exists_query = '''
        select exists (
            select 1
            from tracks
            where fma_track_id = %s
        )'''
    cursor.execute (exists_query, (track_id,))
    return cursor.fetchone()[0]
    

    另一个优点是它总是会返回一个包含布尔值的单行,可以直接使用而无需进一步解释。

    【讨论】:

      【解决方案4】:

      您可以使用rowcount 轻松处理它。这就是psycopg 文档中提到的rowcount

      此只读属性指定最后一次执行*() 产生的行数(对于 SELECT 等 DQL 语句)或受影响(对于 UPDATE 或 INSERT 等 DML 语句)。

      如果没有对游标执行execute*(),则该属性为-1,如果接口无法确定,则为最后一次操作的行数。

      所以下面的例子会让你更好地理解如何使用rowcount


      示例 - 1

      >> # if your SELECT query doesn't have any values you'll get 0 as the output
      >>> query_1 = 'SELECT * FROM some_table LIMIT 0;'
      >>> cursor.execute(query)
      >>> cursor.rowcount
      0
      

      示例 - 2

      >>> query_2 = 'SELECT * FROM some_table LIMIT 1;'
      >>> cursor.execute(query)
      >>> cursor.rowcount
      1
      

      示例 - 3

      >>> # no LIMIT in the query, so you'll get the whole row count
      >>> query_3 = 'SELECT * FROM some_table;'
      >>> cursor.execute(query)
      >>> cursor.rowcount
      14000
      

      示例 - 4

      >>> # this query won't return anything, so you'll get -1 as the rowcount
      >>> query_4 = 'CREATE TABLE new_table AS SELECT * FROM old_table;'
      >>> cursor.execute(query)
      >>> cursor.rowcount
      -1
      

      所以你可以像下面这样修改你的函数,

      def track_exists(self, track_id):
          cur = self.conn.cursor()
          cur.execute("SELECT fma_track_id FROM tracks WHERE fma_track_id = %s", (track_id,))
      
          # if cur.rowcount > 0:
          #     return True
          # else:
          #     return False
      
          return cur.rowcount > 0  # more Pythonic way
      

      请注意:如果您执行UPDATE 查询,您将获得rowcount 的更新行数。所以基本上rowcount 将显示受您的查询影响的行数。 CREATE 查询不会影响任何行,这就是为什么您会为 rowcount 获得 -1

      【讨论】:

        猜你喜欢
        • 2015-03-06
        • 2010-12-24
        • 2015-10-19
        • 2021-11-15
        • 2016-11-05
        • 1970-01-01
        • 2020-02-23
        • 2013-09-19
        • 2013-05-22
        相关资源
        最近更新 更多