Arhn - архитектура программирования

SQLAlchemy получает доступ к типам столбцов из результатов запроса

Я подключаюсь к базе данных SQL Server с помощью SQLAlchemy (с драйвером pymssql).

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):

Первые два элемента (name и type_code) являются обязательными, остальные пять являются необязательными и имеют значение None, если не могут быть предоставлены значимые значения.

Я предполагаю, что целые числа (1, 1, 4, 3, 3) являются типами столбцов.

Мои два вопроса:

  1. Как сопоставить эти целые числа с типами данных (например, char, integer и т. д.)?
  2. Это типы данных SQL? Если нет, можно ли получить типы данных SQL?

FWIW, я получаю тот же результат при использовании raw_connection()< /a> вместо connect().

Наткнулся на три подобных вопроса (которые не отвечают на этот конкретный вопрос). Мне нужно использовать подход connect() + execute().


Ответы:


1

Если нет, можно ли получить типы данных SQL?

Функция SQL Server 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)     |
+-----------------+----------+------------------+

демонстрация db‹›fiddle

17.11.2020
  • Спасибо, я надеялся, что ответ будет где-то в метаданных, но это лучшее, что у меня есть. 23.11.2020

  • 2

    Глядя на PEP249: type_code не похоже на то же самое через другой тип БД.

    Так что этот ответ будет посвящен MS SQL Server.

    1. Как сопоставить эти целые числа с типами данных (например, char, integer и т. д.)?

    Вы можете создать словарь от 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),
        )
    }
    

    Это приведет к следующему dict:

    {2: ('BINARY', <DBAPIType 2>),
     4: ('DATETIME', <DBAPIType 4>),
     5: ('DECIMAL', <DBAPIType 5>),
     3: ('NUMBER', <DBAPIType 3>),
     1: ('STRING', <DBAPIType 1>)}
    

    К сожалению, у меня нет доступа к работающему экземпляру MS SQL Server. Поэтому я не могу проверить, соответствуют ли результаты типа вашему примеру.

    1. Это типы данных SQL? Если нет, можно ли получить типы данных SQL?

    Глядя на PEP и этот результат: эти поля не являются типами данных SQL. Это тип объекта.

    DB API не похож на предоставление методов/функций для проверки метаданных результатов запроса. API просто предоставляет способ привязки типов данных из SQL к типам python.

    Если вам нужно получить точный тип данных SQL, вы должны написать SQL-запрос для конкретного сервера.

    17.11.2020
  • Спасибо, но похоже, что это просто сопоставление кода с типом данных. Меня конкретно интересуют типы данных SQL. 23.11.2020

  • 3

    Это может быть сам водитель. Ниже у меня почти такой же код, как у вас, только с использованием драйвера pyodbc на AdventureWorks. Я выбрал таблицу с множеством разных типов данных, и все они отображаются.

    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))
    

    Вы можете попробовать этот драйвер в качестве сравнения?

    19.11.2020
  • Спасибо, это полезно. Но мне нужно использовать pymssql. 23.11.2020
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..