#游标对象

游标对象(Cursor Object)用于管理对数据库中具体内容的操作,例如执行SQL语句和获取语句执行结果。

# 对象创建方式

游标对象需通过connection.cursor()方法创建。

# 游标方法

方法 说明
Cursor.close() 立即关闭游标。
Cursor.execute() 执行SQL操作,例如查询。
Cursor.executemany() 执行批量SQL操作。
Cursor.fetchone() 获取查询结果集的一行数据,返回单行数据或None,None表示没有可返回的行。
Cursor.fetchmany() 按指定的大小(arraysize属性)获取查询结果集的一部分,返回一个列表,包含指定数量的行,每一行是一个元组(或字典)。
Cursor.fetchall() 一次性获取查询结果集的所有行。
Cursor.var() 创建用于与数据库交互的绑定变量。
Cursor.callproc() 调用存储过程。内部拼接begin proc(...); end;语句执行。

Note:

以下游标方法当前未实现,调用时会抛出NotSupportedError

  • nextset()
  • setinputsizes()
  • setoutputsize()

# 游标属性

属性 说明
Cursor.description: list[FetchInfo] | None 查询结果列信息,获取列名、类型等元数据。
只读,通过执行SQL后自动生成。
Cursor.rowcount: int 最后一个execute()生成或影响的数据行数。
只读,通过执行SQL后自动更新。
Cursor.arraysize: int 指定使用fetchmany()获取的行数。
可写,例如cursor.arraysize = 100

# 上下文管理协议

游标对象支持Python的上下文管理器协议,可使用with语句自动管理游标的生命周期。

# 使用with语句管理游标
with conn.cursor() as cursor:
    cursor.execute("SELECT * FROM table")
    for row in cursor:
        print(row)
# 游标自动关闭

# 迭代协议

游标对象支持迭代协议,可直接遍历查询结果,等价于循环调用fetchone()直至返回None(耗尽结果集时触发StopIteration)。

# 直接迭代游标逐行获取结果
cursor.execute("SELECT * FROM table")
for row in cursor:
    print(row)
# 等价于:
# cursor.execute("SELECT * FROM table")
# while True:
#     row = cursor.fetchone()
#     if row is None:
#         break
#     print(row)

# 完整示例

import yaspy

# 连接数据库
conn = yaspy.connect(dsn="sales/sales@192.168.1.2:1688")

# 创建游标
cursor = conn.cursor()

# 创建测试表
cursor.execute("DROP TABLE IF EXISTS test_cursor")
cursor.execute("""
    CREATE TABLE test_cursor (
        id INT PRIMARY KEY,
        name VARCHAR(50),
        price DECIMAL(10, 2)
    )
""")
conn.commit()
print('Table created')

# 1. execute() - 执行单条SQL
cursor.execute("INSERT INTO test_cursor VALUES (1, 'Apple', 5.99)")
cursor.execute("INSERT INTO test_cursor VALUES (2, 'Banana', 3.50)")
cursor.execute("INSERT INTO test_cursor VALUES (3, 'Orange', 4.25)")
conn.commit()
print('Data inserted via execute()')

# 查看rowcount - 最后执行的SQL影响的行数
print(f'Rows affected: {cursor.rowcount}')

# 2. executemany() - 批量执行SQL
# 方式一:使用命名绑定(字典列表)
data = [
    {"id": 4, "name": "Mango", "price": 6.99},
    {"id": 5, "name": "Grape", "price": 7.50},
    {"id": 6, "name": "Peach", "price": 5.25}
]
cursor.executemany("INSERT INTO test_cursor VALUES (:id, :name, :price)", data)
conn.commit()
print('Data inserted via executemany() (named binding)')

# 方式二:使用位置绑定(元组列表),id 与方式一不重复
data_tuple = [
    (7, 'Pear', 4.99),
    (8, 'Cherry', 8.50),
    (9, 'Plum', 3.25)
]
cursor.executemany("INSERT INTO test_cursor VALUES (:1, :2, :3)", data_tuple)
conn.commit()
print('Data inserted via executemany() (positional binding)')

# 3. fetchone() - 获取单行数据
cursor.execute("SELECT * FROM test_cursor WHERE id = 1")
row = cursor.fetchone()
print(f'fetchone() - Row: id={row[0]}, name={row[1]}, price={row[2]}')

# 4. fetchmany() - 获取多行数据
cursor.execute("SELECT * FROM test_cursor ORDER BY id")
rows = cursor.fetchmany(2)
print(f'fetchmany(2) - Got {len(rows)} rows:')
for row in rows:
    print(f'  id={row[0]}, name={row[1]}, price={row[2]}')

# 设置arraysize属性
cursor.arraysize = 2
cursor.execute("SELECT * FROM test_cursor ORDER BY id")
rows = cursor.fetchmany()
print(f'fetchmany() with arraysize=2 - Got {len(rows)} rows:')
for row in rows:
    print(f'  id={row[0]}, name={row[1]}, price={row[2]}')

# 5. fetchall() - 获取所有数据
cursor.execute("SELECT * FROM test_cursor ORDER BY id")
all_rows = cursor.fetchall()
print(f'fetchall() - Got {len(all_rows)} rows:')
for row in all_rows:
    print(f'  id={row[0]}, name={row[1]}, price={row[2]}')

# 6. description - 获取查询结果列信息
cursor.execute("SELECT id, name, price FROM test_cursor WHERE id = 1")
desc = cursor.description
print('Description:')
for col in desc:
    print(f'  Column: {col[0]}, Type: {col[1]}')

# 7. var() - 创建绑定变量
id_var = cursor.var(yaspy.INTEGER)
name_var = cursor.var(yaspy.VARCHAR)
price_var = cursor.var(yaspy.NUMBER)
id_var.setvalue(7)
name_var.setvalue('Pear')
price_var.setvalue(4.99)
cursor.execute("INSERT INTO test_cursor VALUES (:id, :name, :price)",
               {"id": id_var, "name": name_var, "price": price_var})
conn.commit()
print('Data inserted via var()')

# 验证绑定变量插入的数据
cursor.execute("SELECT * FROM test_cursor WHERE id = 7")
row = cursor.fetchone()
print(f'Verify var() - Row: id={row[0]}, name={row[1]}, price={row[2]}')

# 8. close() - 关闭游标
cursor.close()
print('Cursor closed')

# 清理测试表
conn.cursor().execute("DROP TABLE test_cursor")
conn.commit()
print('Table cleaned up')

# 关闭连接
conn.close()
print('Connection closed')

执行:

Table created
Data inserted via execute()
Rows affected: 1
Data inserted via executemany() (named binding)
Data inserted via executemany() (positional binding)
fetchone() - Row: id=1, name=Apple, price=5.99
fetchmany(2) - Got 2 rows:
  id=1, name=Apple, price=5.99
  id=2, name=Banana, price=3.5
fetchmany() with arraysize=2 - Got 2 rows:
  id=3, name=Orange, price=4.25
  id=4, name=Mango, price=6.99
fetchall() - Got 9 rows:
  id=1, name=Apple, price=5.99
  id=2, name=Banana, price=3.5
  id=3, name=Orange, price=4.25
  id=4, name=Mango, price=6.99
  id=5, name=Grape, price=7.5
  id=6, name=Peach, price=5.25
  id=7, name=Pear, price=4.99
  id=8, name=Cherry, price=8.5
  id=9, name=Plum, price=3.25
Description:
  Column: ID, Type: 4
  Column: NAME, Type: 26
  Column: PRICE, Type: 12
Data inserted via var()
Verify var() - Row: id=7, name=Pear, price=4.99
Cursor closed
Table cleaned up
Connection closed

其中:

  • Table created:测试表创建成功
  • Data inserted via execute():使用execute()插入数据成功
  • Rows affected: 1:最后一条SQL影响的行数
  • Data inserted via executemany() (named binding):使用命名绑定的executemany()批量插入数据成功
  • Data inserted via executemany() (positional binding):使用位置绑定的executemany()批量插入数据成功
  • fetchone() - Row: id=1, name=Apple, price=5.99:获取单行数据
  • fetchmany(2) - Got 2 rows:获取前2行数据(从结果集开头起)
  • fetchmany() with arraysize=2:使用arraysize属性获取数据(游标迭代后从断点继续)
  • fetchall() - Got 9 rows:获取所有9行数据
  • Description:查询结果的列信息。col[0] 为列名,col[1] 为YashanDB数据类型码(4=INTEGER, 26=VARCHAR, 12=FLOAT),非Python内置类型
  • Data inserted via var():使用var()绑定变量插入数据成功
  • Verify var():验证绑定变量插入的数据
  • Cursor closed:游标已关闭
  • Table cleaned up:测试表清理完成
  • Connection closed:连接关闭
edit-icon
反馈
coperate-icon
coperate
合作
communication-icon
communicate
交流