数据对象操作SQLAlchemy ----创建表-used

本文详细介绍使用SQLAlchemy ORM进行数据库操作的全过程,包括表的创建、数据的增删改查及高级查询技巧。通过实例演示了如何高效地进行数据操作。

https://blog.youkuaiyun.com/u012474716/article/details/80175400

1 创建表
from sqlalchemy import MetaData
from sqlalchemy import (Table,Column,Integer,Numeric,String,ForeignKey,create_engine,connectors)
 
 
from datetime import datetime
from sqlalchemy import DateTime
 
metadata=MetaData() #创建metadata对象
cookies = Table('cookies', metadata,
 Column('cookie_id', Integer(), primary_key=True),
 Column('cookie_name', String(50), index=True),
 Column('cookie_recipe_url', String(255)),
 Column('cookie_sku', String(55)),
 Column('quantity', Integer()),
 Column('unit_cost', Numeric(12, 2))
)
 
 
users = Table('users', metadata,
 Column('user_id', Integer(), primary_key=True),
 Column('customer_number', Integer(), autoincrement=True),
 Column('username', String(15), nullable=False, unique=True),
 Column('email_address', String(255), nullable=False),
 Column('phone', String(20), nullable=False),
 Column('password', String(25), nullable=False),
 Column('created_on', DateTime(), default=datetime.now),
 Column('updated_on', DateTime(), default=datetime.now, onupdate=datetime.now)
)
 
orders=Table('orders',metadata,
             Column('order_id',Integer(),primary_key=True),
             Column('user_id',ForeignKey('users.user_id'))  #外键user_id是ForeignKey(users.user_id的主键)
             )
 
line_items = Table('line_items', metadata,
 Column('line_items_id', Integer(), primary_key=True),
 Column('order_id', ForeignKey('orders.order_id')),
 Column('cookie_id', ForeignKey('cookies.cookie_id')),
 Column('quantity', Integer()),
 Column('extended_cost', Numeric(12, 2))
)
 
engine=create_engine('mysql+mysqlconnector://root:root@localhost:3306/imooc') #连接数据库
metadata.create_all(engine) #create_all创建全部的表

插入/更新/删除等操作

插入数据有3种方法:insert

from sqlalchemy import MetaData
from sqlalchemy import (Table,Column,Integer,Numeric,String,ForeignKey,create_engine,connectors)
 
 
from datetime import datetime
from sqlalchemy import DateTime
 
metadata=MetaData()
 
cookies = Table('cookies', metadata,
 Column('cookie_id', Integer(), primary_key=True),
 Column('cookie_name', String(50), index=True),
 Column('cookie_recipe_url', String(255)),
 Column('cookie_sku', String(55)),
 Column('quantity', Integer()),
 Column('unit_cost', Numeric(12, 2))
)
 
engine=create_engine('mysql://root:root@localhost/imooc')
connection=engine.connect()
 
#插入数据方法1==statement语法插入
ins=cookies.insert().values(
 cookie_name="chocolate chip",
 cookie_recipe_url="http://some.aweso.me/cookie/recipe.html",
 cookie_sku="CC01",
 quantity="12",
 unit_cost="0.50"
)
 
print(str(ins))  #打印插入ins的值
 
print ins.compile().params  #compile()是以ins objeect对象返回
 
 
 
#执行插入语句
result = connection.execute(ins)
 
#插入方法2:导入insert方法插入
from sqlalchemy import insert
ins = insert(cookies).values(
    cookie_name="dark chocolate chip",
    cookie_recipe_url="http://some.aweso.me/cookie/recipe_dark.html",
    cookie_sku="CC02",
    quantity="1",
    unit_cost="0.75"
)
 
result = connection.execute(ins)
result.inserted_primary_key
 
#插入方法3:values在执行语句中
ins = cookies.insert()
result = connection.execute(
    ins,
    cookie_name='kk chocolate chip',
    cookie_recipe_url='http://some.aweso.me/cookie/recipe_kk.html',
    cookie_sku='CC04',
    quantity='2',
    unit_cost='2.2'
)
result = connection.execute(ins)
result.inserted_primary_key
 
#批量插入
ins = cookies.insert()
inventory_list = [
    {
        'cookie_name': 'peanut butter',
        'cookie_recipe_url': 'http://some.aweso.me/cookie/peanut.html',
        'cookie_sku': 'PB01',
        'quantity': '24',
        'unit_cost': '0.25'
},
 {
'cookie_name': 'oatmeal raisin',
'cookie_recipe_url': 'http://some.okay.me/cookie/raisin.html',
'cookie_sku': 'EWW01',
'quantity': '100',
'unit_cost': '1.00'
 }
]
 
result=connection.execute(ins,inventory_list) #ins是方法,inventory_list是批量插入的值

 

查询数据:select

from sqlalchemy import MetaData
from sqlalchemy import (Table,Column,Integer,Numeric,String,ForeignKey,create_engine,connectors)
 
 
metadata=MetaData()
 
cookies = Table('cookies', metadata,
 Column('cookie_id', Integer(), primary_key=True),
 Column('cookie_name', String(50), index=True),
 Column('cookie_recipe_url', String(255)),
 Column('cookie_sku', String(55)),
 Column('quantity', Integer()),
 Column('unit_cost', Numeric(12, 2))
)
 
 
engine=create_engine('mysql://root:root@localhost/imooc')
connection=engine.connect()
 
#select取出所有数据
from sqlalchemy.sql import select
s = cookies.select()
rp = connection.execute(s)
results = rp.fetchall()
print results
first_row=results[0]
#下面3条都取出cookie_name
print first_row[1]
print first_row.cookie_name
print first_row[cookies.c.cookie_name]
print "++++++++++++++++++++++++++++++++++++++++"
 
#select取出部分字段数据
s=select([cookies.c.cookie_name,cookies.c.cookie_sku,cookies.c.quantity])
rp=connection.execute(s)
results=rp.fetchall()
print results
print '++++++++++++++++++++++++++++++++++++++++'
#返回的结果
#[('chocolate chip', 'CC01', 12L), ('dark chocolate chip', 'CC02', 1L)]
 
 
#取出每条信息
# 它可以类似字典一样取出字段值:record.cookie_name,字段名就相当于key.取出所有值中字段名为cookie_name的值
#而未导入sqlalchemy则,纯python元组是a[0]取数据,字典才会a["key"]取出值
rp=connection.execute(s)
for record in rp:
  print record   #结果是元组:('chocolate chip', 'CC01', 12L)
  print (record.cookie_name)
print '++++++++++++++++++++++++++++++++++++++++++'
 
#查看字段名,取出第一条记录
s=select([cookies.c.cookie_name,cookies.c.quantity])
rp=connection.execute(s)
print(rp.keys()) #rp.keys()是字段名 结果:['cookie_name', 'quantity']
results=rp.first() #取出第一条记录
print results

排序:order_by

限制返回记录条数:limit()

#排序(升序)
s=select([cookies.c.cookie_name,cookies.c.quantity])
s=s.order_by(cookies.c.quantity)
#或者合并成下面的一条语句
# s=select([cookies.c.cookie_name,cookies.c.quantity]).order_by(cookies.c.quantity)
#降序
from sqlalchemy import desc
s=select([cookies.c.cookie_name,cookies.c.quantity]).order_by(desc(cookies.c.quantity))
 
rp=connection.execute(s)
for cookie in rp:
  print ('{} - {}'.format(cookie.quantity,cookie.cookie_name))
 
#限制条数
s=select([cookies.c.cookie_name,cookies.c.quantity])
s=s.order_by(cookies.c.quantity)
s=s.limit(2)
rp=connection.execute(s)
print ([result.cookie_name for result in rp])

内嵌入sql函数:sum/count等

from sqlalchemy.sql import select
from sqlalchemy import MetaData
from sqlalchemy import (Table,Column,Integer,Numeric,String,ForeignKey,create_engine,connectors)
 
 
metadata=MetaData()
 
cookies = Table('cookies', metadata,
 Column('cookie_id', Integer(), primary_key=True),
 Column('cookie_name', String(50), index=True),
 Column('cookie_recipe_url', String(255)),
 Column('cookie_sku', String(55)),
 Column('quantity', Integer()),
 Column('unit_cost', Numeric(12, 2))
)
 
engine=create_engine('mysql://root:root@localhost/imooc')
connection=engine.connect()
 
#内嵌入sql函数
# 如sum,count等,它打包在column(s)方法中
from sqlalchemy.sql import func
s=select([func.sum(cookies.c.quantity)])
rp=connection.execute(s)
print rp  #rp是一个对象
print(rp.scalar()) #取rp对象里的值  #返回结果是:151
 
#计数
s=select([func.count(cookies.c.cookie_name)])
rp=connection.execute(s)
record=rp.first()
print (record.keys())
print (record.count_1) #count总计多少条记录,列名为count_1
#返回结果如下
# [u'count_1']
#   6
 
#count列也可以用label取个别名
s=select([func.count(cookies.c.cookie_name).label('inventory_count')])
rp=connection.execute(s)
record=rp.first()
print (record.keys())
print (record.inventory_count)
#返回的结果:
# ['inventory_count']
#    6

过滤:where

#where过滤条件
#cookies.c. c相当于column
s=select([cookies]).where(cookies.c.cookie_name=='chocolate chip')
rp=connection.execute(s)
record=rp.first()
print(record.items())
 
#like模糊过滤查找
s=select([cookies]).where(cookies.c.cookie_name.like('%chocolate%'))
rp=connection.execute(s)
for record in rp.fetchall():
  print (record.cookie_name)

过滤条件中常用的方法:
between(cleft,cright)
concat(column_two)
distinct()
in_([list])
is_(None)
contains(string)
endswith(string)
like(string)
startswith(string)
ilike(string)

操作:

from sqlalchemy.sql import select
from sqlalchemy import MetaData
from sqlalchemy import (Table,Column,Integer,Numeric,String,ForeignKey,create_engine,connectors)
 
 
metadata=MetaData()
 
cookies = Table('cookies', metadata,
 Column('cookie_id', Integer(), primary_key=True),
 Column('cookie_name', String(50), index=True),
 Column('cookie_recipe_url', String(255)),
 Column('cookie_sku', String(55)),
 Column('quantity', Integer()),
 Column('unit_cost', Numeric(12, 2))
)
 
engine=create_engine('mysql://root:root@localhost/imooc')
connection=engine.connect()
 
#字符串连接:'+'
s=select([cookies.c.cookie_name,'SKU-'+cookies.c.cookie_sku])
for row in connection.execute(s):
   print(row)
 
#cast
from sqlalchemy import cast
s=select([cookies.c.cookie_name,cast((cookies.c.quantity * cookies.c.unit_cost),
                                     Numeric(12,2)).label('inv_cost')])
for row in connection.execute(s):
   print ('{} - {}'.format(row.cookie_name,row.inv_cost))
 
#布尔型(&,|,and)
#若想得到(A<B) & (C<D)用连接更高效
#连接conjunctions
# and_
from sqlalchemy import and_,or_,not_
s=select([cookies]).where(
   and_(
      cookies.c.quantity>23,
      cookies.c.unit_cost<0.40
   )
)
for row in connection.execute(s):
   print (row.cookie_name)
# or_
s=select([cookies]).where(
   or_(
      cookies.c.quantity.between(10,50),
      cookies.c.cookie_name.contains('chip')
   )
)
for row in connection.execute(s):
    print(row.cookie_name)

更新:update

from sqlalchemy import update
from sqlalchemy import select
from sqlalchemy import MetaData
from sqlalchemy import (Table,Column,Integer,Numeric,String,ForeignKey,create_engine,connectors)
 
 
metadata=MetaData()
 
cookies = Table('cookies', metadata,
 Column('cookie_id', Integer(), primary_key=True),
 Column('cookie_name', String(50), index=True),
 Column('cookie_recipe_url', String(255)),
 Column('cookie_sku', String(55)),
 Column('quantity', Integer()),
 Column('unit_cost', Numeric(12, 2))
)
 
engine=create_engine('mysql://root:root@localhost/imooc')
connection=engine.connect()
 
u=update(cookies).where(cookies.c.cookie_name=='chocolate chip')
u=u.values(quantity=(cookies.c.quantity+120))
result=connection.execute(u)
print (result.rowcount)
s=select([cookies]).where(cookies.c.cookie_name=='chocolate chip')
result=connection.execute(s).first()
for key in result.keys():
    print('{:>20}:{}'.format(key,result[key]))

删除:Delete

from sqlalchemy import delete
from sqlalchemy import select
from sqlalchemy import MetaData
from sqlalchemy import (Table,Column,Integer,Numeric,String,ForeignKey,create_engine,connectors)
 
 
metadata=MetaData()
 
cookies = Table('cookies', metadata,
 Column('cookie_id', Integer(), primary_key=True),
 Column('cookie_name', String(50), index=True),
 Column('cookie_recipe_url', String(255)),
 Column('cookie_sku', String(55)),
 Column('quantity', Integer()),
 Column('unit_cost', Numeric(12, 2))
)
 
engine=create_engine('mysql://root:root@localhost/imooc')
connection=engine.connect()
 
u=delete(cookies).where(cookies.c.cookie_name=='dark chocolate chip')
result=connection.execute(u)
print (result.rowcount)
 
s=select([cookies]).where(cookies.c.cookie_name=='dark chocolate chip')
result=connection.execute(s)
print (len(result))

 

 

<think>首先,用户的问题是:解决 'TypeError: dict can not be used as parameter' 错误的方案。用户提供了多个引用,我需要参考这些引用。 回顾引用: - 引用[1]: 提到使用 json.dumps 序列化来解决 TypeError: dict can not be used as parameter。建议先把 list/dict 序列化成 JSON 字符串。 - 引用[2]: 关于 Python 内置数据结构 dict 的创建方法,但没有直接解决错误。 - 引用[3]: 涉及数据库游标和 SQL 执行,提到类似错误,但不是直接针对这个错误。 - 引用[4]: 讨论 TypeError: unhashable type: 'dict' or 'list',并给出一个例子,错误在于使用 list 或 dict 作为字典的键。 - 引用[5]: 关于 SQLAlchemy 中的 TypeError: unhashable type: 'dict',提到 bind 参数的问题。 用户的问题核心是 'TypeError: dict can not be used as parameter'。从引用看,这个错误通常发生在尝试将字典作为参数传递给某些函数时,比如在 SQL 执行或类似上下文中。 关键点: - 引用[1] 直接提到解决方案:使用 json.dumps 序列化字典为 JSON 字符串。 - 引用[4] 和 [5] 讨论类似的错误 TypeError: unhashable type: 'dict',这通常是因为试图使用字典作为集合的键或字典的键,而字典是不可哈希的。 在 Python 中,字典是不可哈希的类型,所以不能用作字典的键或集合的元素。类似地,在某些需要特定参数类型的函数中,如 SQL 执行函数,它们可能要求字典被序列化或转换为适当格式。 常见场景: - 在数据库操作中,如 cursor.executemany(insert_data, param),其中 param 应该是一个序列(如列或元组),但如果 param 中包含字典或其他不可哈希对象,可能会导致错误。 - 解决方案:序列化字典为字符串,比如使用 JSON 序列化。 用户引用的错误是 'dict can not be used as parameter',这可能具体指一个函数不接受字典作为参数。 从引用[1]:"TypeError: dict can not be used as parameter",并且解决方案是使用 json.dumps 序列化。 所以,我的回答应该基于这个。 回答结构: - 解释错误原因:为什么会出现这个错误? - 提供解决方案:如何解决? - 参考引用:自然地添加引用标识。 根据系统指令: - 使用中文回答。 - 结构清晰,帮助用户逐步解决问题。 - 生成相关问题(在末尾)。 - 对于数学达式,使用 $...$ 或 $$...$$,但这个问题可能不涉及数学达式,所以可能不需要。 - 引用的段落末尾添加引用标识,例如:[^1] 错误的原因:在 Python 中,某些函数或方法要求参数是特定类型。例如,在执行 SQL 语句时,参数应该是一个元组或列,而不是字典,因为字典是不可序列化的或不被直接支持。 解决方案: 1. 序列化字典:使用 json.dumps(dict) 将字典转换为 JSON 字符串。然后传递字符串作为参数。 2. 在数据库上下文中,正确使用参数化查询。 步骤: - 识别错误的上下文:通常在数据库操作、API 调用或其他需要序列化数据的地方。 - 修改代码:将字典序列化。 示例代码:基于引用[1],给出类似示例。 生成相关问题:在回答末尾添加相关问题。 参考引用: - [^1] 提到序列化解决方案。 - [^4] 和 [^5] 可参考为类似错误。 回答大纲: 1. **解释错误原因**:当尝试将字典作为参数传递给某些函数时,Python 会抛出 TypeError: dict can not be used as parameter。这是因为字典是不可哈希类型,在某些上下文中不被直接接受。常见于数据库操作或需要序列化数据的场景。[^1][^4] 2. **提供解决方案**: - 使用 json.dumps 序列化字典为 JSON 字符串。 - 示例:将字典参数序列化后再传递。 - 其他上下文:在数据库 cursor.execute 中,确保参数是元组或列。 3. **代码示例**:给出一个简单的代码片段演示如何修复。 4. **生成相关问题**:在 §§相关问题§§ 部分列出。 代码示例基于引用[1]: 原始错误代码可能像这样: ```python # 假设错误代码 param = {'key': 'value'} some_function(param) # 抛出 TypeError: dict can not be used as parameter ``` 修复后: ```python import json param = {'key': 'value'} serialized_param = json.dumps(param) # 序列化为 JSON 字符串 some_function(serialized_param) # 现在传递字符串 ``` 在数据库上下文中,引用[3] 显示了类似场景,使用 cursor.executemany,参数应该是列的列或类似结构。 最后,相关问题: 1. 如何预防这种类型错误? 2. JSON 序列化和反序列化的最佳实践。 3. 在 Python 中,字典和其他数据结构的常见错误处理。 确保回答真实可靠。 </think>### 解决 'TypeError: dict can not be used as parameter' 错误 在 Python 中,`TypeError: dict can not be used as parameter` 错误通常发生在尝试将字典作为参数传递给某些函数时,而该函数要求参数为特定类型(如字符串、元组或列)。字典是不可哈希的类型,在需要序列化或严格参数类型的上下文中(如数据库操作、API 调用或某些内置函数)不被直接支持。常见场景包括 SQL 执行函数(如 `cursor.execute()`)或 JSON 处理函数。下面我将逐步解释错误原因并提供解决方案,确保代码可运行可靠。 #### 1. **错误原因分析** - **字典的特性**:Python 字典(`dict`)是可变对象,不可哈希(unhashable),这意味着它不能被用作字典的键或集合的元素。在某些函数参数中,如果该函数设计为接受字符串、元组或列,但传入字典会导致类型错误[^1][^4]。 - **常见触发场景**: -使用数据库游标(如 `mysql.connector` 或 `SQLAlchemy`)执行 SQL 语句时,参数必须是序列化格式(如元组),而非字典。 - 在 JSON 处理中,如果直接传递字典作为参数(如某些 API 函数),需要先序列化为字符串。 - 尝试将字典用于字典键值(如 `b = {a: value}` 中的键 `a` 是字典),这会引发类似错误[^1][^4][^5]。 - **错误本质**:Python 的参数传递机制要求参数类型匹配;如果函数预期为简单类型(如字符串),但传入复杂对象(如字典),则会抛出此错误[^1][^4]。 #### 2. **解决方案:使用 JSON 序列化** 最可靠的解决方法是使用 `json.dumps()` 将字典序列化为 JSON 字符串,然后再传递该字符串作为参数。JSON 字符串是可哈希的类型,能被大多数函数接受。以下是详细步骤和代码示例: **步骤说明**: 1. **导入 json 模块**:确保在代码开头导入 Python 的 `json` 模块。 2. **序列化字典**:使用 `json.dumps(dict)` 将字典转换为 JSON 字符串。 3. **传递序列化后的参数**:将字符串而不是原始字典传递给函数。 4. **反序列化(如果需要)**:在接收端,使用 `json.loads()` 将字符串还原为字典。 **代码示例**: 假设在数据库操作中遇到错误(如引用[3]的场景),以下示例展示了如何修复: ```python import json import mysql.connector # 错误场景:直接传递字典参数导致 TypeError # param = [{'id': 1, 'name': 'Alice'}] # 如果直接作为参数,会报错 # 解决方案:序列化字典为 JSON 字符串 data_list = [{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}] # 原始字典列 serialized_data = [json.dumps(item) for item in data_list] # 序列化每个字典为字符串 # 连接到数据库并执行 SQL conn = mysql.connector.connect(host="localhost", user="root", password="", database="test") cursor = conn.cursor() # 创建示例(假设结构为: id INT, data JSON) cursor.execute("CREATE TABLE IF NOT EXISTS users (id INT PRIMARY KEY, data JSON)") # 正确执行 SQL:参数使用序列化后的字符串列 insert_query = "INSERT INTO users (id, data) VALUES (%s, %s)" for item in serialized_data: # 参数化查询:第一个参数是 id,第二个是序列化后的字符串 cursor.execute(insert_query, (item['id'], item)) # 注意:在实际中,item 是字符串,但这里为演示简化逻辑 conn.commit() cursor.close() conn.close() ``` - **关键点**: - `json.dumps()` 将字典转换为字符串(如 `'{"id": 1, "name": "Alice"}'`),避免类型错误[^1]。 - 在数据库操作中,确保参数列(如 `(item['id'], item)`)的元素是基本类型(整数、字符串等)。 - 如果函数需要字典格式的结构(如某些 ORM 工具),确保绑定参数时使用正确类型(如引用[5] 中提到的 `binds` 参数处理)[^5]。 **其他场景的适配**: - **API 调用**:如果函数要求字符串参数(如 HTTP 请求),序列化字典: ```python import requests import json data_dict = {'key': 'value'} serialized_data = json.dumps(data_dict) # 序列化 response = requests.post('https://api.example.com', data=serialized_data) # 传递字符串 ``` - **字典作为键**:避免直接使用字典作为字典的键(引发 `TypeError: unhashable type: 'dict'`),改用元组或字符串: ```python # 错误:a = {'a': 1}; b = {a: 'value'} # 报错 # 修复:使用序列化键 a = {'a': 1} b_key = json.dumps(a) # 序列化为字符串键 b = {b_key: 'value'} # 正常 ``` #### 3. **预防和最佳实践** - **参数检查**:在传递参数前,使用 `isinstance(param, (str, tuple, list))` 检查类型,确保兼容性。 - **数据库操作优化**:使用参数化查询(如 `cursor.executemany()`),并确保传入的参数是列或元组(而非字典),如引用[3] 所示[^3]。 - **错误处理**:添加 try-except 块捕获 `TypeError`,并提供友好的错误信息: ```python try: some_function(param) except TypeError as e: print(f"错误:参数类型不匹配。建议序列化字典:{e}") ``` - **性能考量**:序列化增加轻微开销,但对于大多数应用影响很小;如果性能敏感,考虑使用 `pickle` 或自定义序列化(但 JSON 更通用)[^1]。 通过以上步骤,您可以有效解决 `TypeError: dict can not be used as parameter` 相关问题。如果错误出现在特定库(如 SQLAlchemy),检查库文档中对参数类型的要求,确保正确使用绑定参数[^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值