SQLAlchemy 从查询结果中访问列类型
SQLAlchemy accessing column types from query results
我正在使用 SQLAlchemy(使用 pymssql
驱动程序)连接到 SQL 服务器数据库。
import sqlalchemy
conn_string = f'mssql+pymssql://{uid}:{pwd}@{instance}/?database={db};charset=utf8'
sql = 'SELECT * FROM FAKETABLE;'
engine = sqlalchemy.create_engine(conn_string)
connection = engine.connect()
result = connection.execute(sql)
result.cursor.description
这导致:
(('col_1', 1, None, None, None, None, None),
('col_2', 1, None, None, None, None, None),
('col_3', 4, None, None, None, None, None),
('col_4', 3, None, None, None, None, None),
('col_5', 3, None, None, None, None, None))
根据 PEP 249(游标的 .description
属性):
The first two items (name and type_code) are mandatory, the other five are optional and are set to None if no meaningful values can be provided.
我假设整数 (1, 1, 4, 3, 3)
是列类型。
我的两个问题:
- 如何将这些整数映射到数据类型(如字符、整数等)?
- 这些是 SQL 数据类型吗?如果不是,是否可以获取 SQL 数据类型?
FWIW,我在使用 raw_connection()
而不是 connect()
时得到相同的结果。
遇到了三个类似的问题(没有回答这个具体问题)。我需要使用 connect()
+ execute()
方法。
- SQLAlchemy getting column data types of query results
- How to get columns' sql type queried by sqlalchemy
- Easy convert betwen SQLAlchemy column types and python data types?
If no, is it possible to get the SQL data types?
SQL 服务器函数 sys.dm_exec_describe_first_result_set 可用于为提供的查询直接获取 SQL 列的数据类型:
SELECT column_ordinal, name, system_type_name, *
FROM sys.dm_exec_describe_first_result_set('here goes query', NULL, 0) ;
在你的例子中:
sql = """SELECT column_ordinal, name, system_type_name
FROM sys.dm_exec_describe_first_result_set('SELECT * FROM FAKETABLE', NULL, 0) ;"""
对于:
CREATE TABLE FAKETABLE(id INT, d DATE, country NVARCHAR(10));
SELECT column_ordinal, name, system_type_name
FROM sys.dm_exec_describe_first_result_set('SELECT * FROM FAKETABLE', NULL, 0) ;
+-----------------+----------+------------------+
| column_ordinal | name | system_type_name |
+-----------------+----------+------------------+
| 1 | id | int |
| 2 | d | date |
| 3 | country | nvarchar(10) |
+-----------------+----------+------------------+
查看PEP249:type_code
看起来不一样,通过不同的数据库类型。
所以这个答案将集中在 MS SQL 服务器上。
- How to map these integers to data types (like char, integer, etc.)?
您可以使用以下代码创建 type_code
到 type_object
的字典:
import inspect
import pymssql
code_map = {
type_obj.value: (type_name, type_obj)
for type_name, type_obj
in inspect.getmembers(
pymssql,
predicate=lambda x: isinstance(x, pymssql.DBAPIType),
)
}
这将产生以下字典:
{2: ('BINARY', <DBAPIType 2>),
4: ('DATETIME', <DBAPIType 4>),
5: ('DECIMAL', <DBAPIType 5>),
3: ('NUMBER', <DBAPIType 3>),
1: ('STRING', <DBAPIType 1>)}
不幸的是,我无法访问 MS SQL 服务器的 运行 实例。所以我无法检查类型结果是否与您的示例匹配。
- Are these SQL data types? If no, is it possible to get the SQL data types?
查看 PEP 和此结果:此字段不是 SQL 数据类型。这是“类型对象”。
DB API 看起来没有提供检查查询结果元数据的方法/函数。 API 只是提供了一种将数据类型从 SQL 绑定到 python 类型的方法。
如果您需要获取准确的 SQL 数据类型,那么您必须编写特定于服务器的 SQL 查询。
可能是驱动本身。下面我有几乎和你一样的代码,只是使用 AdventureWorks 上的 pyodbc 驱动程序。我选择了一个有很多不同数据类型的 table,它们都在显示。
import sqlalchemy
conn_string = conn_string = f'mssql+pyodbc://{username}:{pwd}@{instance}/AdventureWorksLT2017?driver=ODBC+Driver+17+for+SQL+Server'
sql = 'SELECT TOP 10 * FROM SalesLT.Product;'
engine = sqlalchemy.create_engine(conn_string)
connection = engine.connect()
result = connection.execute(sql)
print(result.cursor.description)
输出:
(('ProductID', <class 'int'>, None, 10, 10, 0, False), ('Name', <class 'str'>, None, 50, 50, 0, False), ('ProductNumber', <class 'str'>, None, 25, 25, 0, False), ('Color', <class 'str'>, None, 15, 15, 0, True), ('StandardCost', <class 'decimal.Decimal'>, None, 19, 19, 4, False), ('ListPrice', <class 'decimal.Decimal'>, None, 19, 19, 4, False), ('Size', <class 'str'>, None, 5, 5, 0, True), ('Weight', <class 'decimal.Decimal'>, None, 8, 8, 2, True), ('ProductCategoryID', <class 'int'>, None, 10, 10, 0, True), ('ProductModelID', <class 'int'>, None, 10, 10, 0, True), ('SellStartDate', <class 'datetime.datetime'>, None, 23, 23, 3, False), ('SellEndDate', <class 'datetime.datetime'>, None, 23, 23, 3, True), ('DiscontinuedDate', <class 'datetime.datetime'>, None, 23, 23, 3, True), ('ThumbNailPhoto', <class 'bytearray'>, None, 0, 0, 0, True), ('ThumbnailPhotoFileName', <class 'str'>, None, 50, 50, 0, True), ('rowguid', <class 'str'>, None, 36, 36, 0, False), ('ModifiedDate', <class 'datetime.datetime'>, None, 23, 23, 3, False))
你能试试这个驱动程序作为比较吗?
我正在使用 SQLAlchemy(使用 pymssql
驱动程序)连接到 SQL 服务器数据库。
import sqlalchemy
conn_string = f'mssql+pymssql://{uid}:{pwd}@{instance}/?database={db};charset=utf8'
sql = 'SELECT * FROM FAKETABLE;'
engine = sqlalchemy.create_engine(conn_string)
connection = engine.connect()
result = connection.execute(sql)
result.cursor.description
这导致:
(('col_1', 1, None, None, None, None, None),
('col_2', 1, None, None, None, None, None),
('col_3', 4, None, None, None, None, None),
('col_4', 3, None, None, None, None, None),
('col_5', 3, None, None, None, None, None))
根据 PEP 249(游标的 .description
属性):
The first two items (name and type_code) are mandatory, the other five are optional and are set to None if no meaningful values can be provided.
我假设整数 (1, 1, 4, 3, 3)
是列类型。
我的两个问题:
- 如何将这些整数映射到数据类型(如字符、整数等)?
- 这些是 SQL 数据类型吗?如果不是,是否可以获取 SQL 数据类型?
FWIW,我在使用 raw_connection()
而不是 connect()
时得到相同的结果。
遇到了三个类似的问题(没有回答这个具体问题)。我需要使用 connect()
+ execute()
方法。
- SQLAlchemy getting column data types of query results
- How to get columns' sql type queried by sqlalchemy
- Easy convert betwen SQLAlchemy column types and python data types?
If no, is it possible to get the SQL data types?
SQL 服务器函数 sys.dm_exec_describe_first_result_set 可用于为提供的查询直接获取 SQL 列的数据类型:
SELECT column_ordinal, name, system_type_name, *
FROM sys.dm_exec_describe_first_result_set('here goes query', NULL, 0) ;
在你的例子中:
sql = """SELECT column_ordinal, name, system_type_name
FROM sys.dm_exec_describe_first_result_set('SELECT * FROM FAKETABLE', NULL, 0) ;"""
对于:
CREATE TABLE FAKETABLE(id INT, d DATE, country NVARCHAR(10));
SELECT column_ordinal, name, system_type_name
FROM sys.dm_exec_describe_first_result_set('SELECT * FROM FAKETABLE', NULL, 0) ;
+-----------------+----------+------------------+
| column_ordinal | name | system_type_name |
+-----------------+----------+------------------+
| 1 | id | int |
| 2 | d | date |
| 3 | country | nvarchar(10) |
+-----------------+----------+------------------+
查看PEP249:type_code
看起来不一样,通过不同的数据库类型。
所以这个答案将集中在 MS SQL 服务器上。
- How to map these integers to data types (like char, integer, etc.)?
您可以使用以下代码创建 type_code
到 type_object
的字典:
import inspect
import pymssql
code_map = {
type_obj.value: (type_name, type_obj)
for type_name, type_obj
in inspect.getmembers(
pymssql,
predicate=lambda x: isinstance(x, pymssql.DBAPIType),
)
}
这将产生以下字典:
{2: ('BINARY', <DBAPIType 2>),
4: ('DATETIME', <DBAPIType 4>),
5: ('DECIMAL', <DBAPIType 5>),
3: ('NUMBER', <DBAPIType 3>),
1: ('STRING', <DBAPIType 1>)}
不幸的是,我无法访问 MS SQL 服务器的 运行 实例。所以我无法检查类型结果是否与您的示例匹配。
- Are these SQL data types? If no, is it possible to get the SQL data types?
查看 PEP 和此结果:此字段不是 SQL 数据类型。这是“类型对象”。
DB API 看起来没有提供检查查询结果元数据的方法/函数。 API 只是提供了一种将数据类型从 SQL 绑定到 python 类型的方法。
如果您需要获取准确的 SQL 数据类型,那么您必须编写特定于服务器的 SQL 查询。
可能是驱动本身。下面我有几乎和你一样的代码,只是使用 AdventureWorks 上的 pyodbc 驱动程序。我选择了一个有很多不同数据类型的 table,它们都在显示。
import sqlalchemy
conn_string = conn_string = f'mssql+pyodbc://{username}:{pwd}@{instance}/AdventureWorksLT2017?driver=ODBC+Driver+17+for+SQL+Server'
sql = 'SELECT TOP 10 * FROM SalesLT.Product;'
engine = sqlalchemy.create_engine(conn_string)
connection = engine.connect()
result = connection.execute(sql)
print(result.cursor.description)
输出:
(('ProductID', <class 'int'>, None, 10, 10, 0, False), ('Name', <class 'str'>, None, 50, 50, 0, False), ('ProductNumber', <class 'str'>, None, 25, 25, 0, False), ('Color', <class 'str'>, None, 15, 15, 0, True), ('StandardCost', <class 'decimal.Decimal'>, None, 19, 19, 4, False), ('ListPrice', <class 'decimal.Decimal'>, None, 19, 19, 4, False), ('Size', <class 'str'>, None, 5, 5, 0, True), ('Weight', <class 'decimal.Decimal'>, None, 8, 8, 2, True), ('ProductCategoryID', <class 'int'>, None, 10, 10, 0, True), ('ProductModelID', <class 'int'>, None, 10, 10, 0, True), ('SellStartDate', <class 'datetime.datetime'>, None, 23, 23, 3, False), ('SellEndDate', <class 'datetime.datetime'>, None, 23, 23, 3, True), ('DiscontinuedDate', <class 'datetime.datetime'>, None, 23, 23, 3, True), ('ThumbNailPhoto', <class 'bytearray'>, None, 0, 0, 0, True), ('ThumbnailPhotoFileName', <class 'str'>, None, 50, 50, 0, True), ('rowguid', <class 'str'>, None, 36, 36, 0, False), ('ModifiedDate', <class 'datetime.datetime'>, None, 23, 23, 3, False))
你能试试这个驱动程序作为比较吗?