#游标对象
游标对象(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:连接关闭

