Проблема с вставкой данных на сервер Sql с использованием Python Pandas Dataframe - PullRequest
0 голосов
/ 10 апреля 2019

Я пытаюсь извлечь данные из REST API и вставить их в SQL Server. Если у нас есть скрипт, выполняющий PhotoBinary, Filetype вместе, он работает, но как только я добавлю идентификатор, который является целым числом, мы получим ошибку ниже. Кроме того, если я просто получаю идентификатор самостоятельно из API, это работает.

Я пытаюсь получить 3 элемента информации

  1. Идентификатор сотрудника, который является целым.
  2. Двоичное строковое представление изображения
  3. Тип файла исходного файла, например: .jpg

Таблица назначения настроена как:

Create table Employee_Photo
( 
    EmployeeID  int,
    PhotoBinary varchar(max),
    FileType varchar(10)
)

Ошибка, которую я получаю:

Traceback (most recent call last):
  File "apiphotopullwithid.py", line 64, in <module>
    cursor.execute("INSERT INTO dbo.Employee_Photo([EmployeeID],[PhotoBinary],[FileType]) values (?,?,?)", row['EMPID'],row['Photo'],row['PhotoType'])
pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 5 (""): The supplied value is not a valid instance of data type float. Check the source data for invalid values. An example of an invalid value is data of numeric type with scale greater than precision. (8023) (SQLExecDirectW)')
import json
import pandas as pd
import sqlalchemy
import pyodbc
import requests

url = "https://someurl.com/api/PersonPhoto"

headers = {
    'Accept': "application/json",
    'Authorization': "apikey XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    'Content-Type': "application/json",
    'cache-control': "no-cache"
}

response = requests.request("GET", url, headers=headers)
data = json.loads(response.text)


ID,Photo,PhotoType = [],[],[]

for device in data['PersonPhoto']:
    ID.append(device[u'ID'])

    Photo.append(device[u'Photo'])

    PhotoType.append(device[u'PhotoType'])


df = pd.DataFrame([ID,Photo,PhotoType]).T
df.columns = ['EMPID','Photo','PhotoType']
df = df.astype({'EMPID':'Int64'})



connStr = pyodbc.connect(
    "DRIVER={SQL Server};"
    "SERVER=SQLTest;"
    "Database=Intranet123;"
    "Trusted_Connection=yes;"
    #"UID=ConnectME;"
    #"PWD={Password1}"
)
cursor = connStr.cursor()

for index,row in df.iterrows():
cursor.execute("INSERT INTO dbo.Employee_Photo([EmployeeID],[PhotoBinary],[FileType]) values (?,?,?)", row['EMPID'],row['Photo'],row['PhotoType']) 
    connStr.commit()
    cursor.close()
connStr.close()

Ответы [ 2 ]

0 голосов
/ 10 апреля 2019

В большинстве API баз данных Python, включая pyodbc, придерживающихся спецификаций PEP 249 , аргумент parameters в cursor.execute() обычно представляет собой последовательность (т. Е. Кортеж, список).Поэтому свяжите все значения в итеративный, а не как три отдельных значения аргумента:

sql = "INSERT INTO dbo.Employee_Photo ([EmployeeID],[PhotoBinary],[FileType]) VALUES (?,?,?)"

# TUPLE
cursor.execute(sql, (row['EMPID'], row['Photo'], row['PhotoType']))

# LIST
cursor.execute(sql, [row['EMPID'], row['Photo'], row['PhotoType']])

Кстати, избегайте явного цикла iterrows и используйте неявный цикл с executemanyиспользуя Pandas ' DataFrame.values ​​:

# EXECUTE PARAMETERIZED QUERY
sql_cols = ['EMPID', 'Photo', 'PhotoType']
cursor.executemany(sql, df[sql_cols].values.tolist())   
conn.commit()

На самом деле вам даже не нужен Pandas в качестве среднего уровня (используйте библиотеку только для обработки данных) и взаимодействуйте с оригиналом, возвращеннымJSON:

# NESTED LIST OF TUPLES
vals = [(int(device[u'ID']), device[u'Photo'], device[u'PhotoType']) \
           for device in data['PersonPhoto']]

cursor.executemany(sql, vals)   
conn.commit()
0 голосов
/ 10 апреля 2019

Вы используете старый драйвер Windows Server для Windows.Попробуйте новый, который вы можете получить от здесь для нескольких платформ.

Не читайте слишком много в сообщении об ошибке.Что-то искажено на уровне сетевого протокола.

Можете ли вы сбросить типы и значения параметров, вызывающих проблему.Я предполагаю, что драйвер неправильно устанавливает типы параметров.

EG:

for index,row in df.iterrows():
  empid =  row['EMPID']
  photo = row['Photo']
  photoType = row['PhotoType']

  print("empid is ",type(empid), " photo is ", type(photo), " photoType is ", type(photoType))
  print("empid: ",empid, " photo: ", photo, " photoType: ", photoType)

  cursor.execute("INSERT INTO dbo.Employee_Photo([EmployeeID],[PhotoBinary],[FileType]) values (?,?,?)", empid,photo,photoType) 

connStr.commit()
cursor.close()
connStr.close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...