Я пытаюсь загрузить файл XML в таблицу базы данных сервера SQL, и он с треском проваливается, и я действительно не могу заставить его работать. Любая идея будет принята с благодарностью!
Код выглядит следующим образом (с большим количеством комментариев, адресованных самому себе) - я перебираю папки для загрузки целой пачки файлов, но один из них для начала был бы хорош !
# finding the right modules/packages to use is not easy
import os
import pyodbc
from numpy import genfromtxt
import pandas as pd
import sqlalchemy as sa # use sqlalchemy for truncating etc
from sqlalchemy import Column, Integer, Float, Date, String, BigInteger
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.dialects import mssql
import urllib
import csv
import fnmatch2
from time import time
## DATABASE STUFF
# server + instance = DESKTOP01\MYINSTANCE
# database = Tracks
server_name='DESKTOP01\MYINSTANCE'
db_name='Tracks'
path = 'F:\export_6642035' # location of all the files related to STRAVA export
pathArchive = 'F:\export_6642035_archive' # this is the archive folder that will contain all the processed files
searchstring = '*' # we could limit the files to a particular string pattern, however in this case we want to go through all the files
params = urllib.parse.quote_plus('Driver={SQL Server};'
'Server='+server_name +';'
'Database='+db_name+';'
'Trusted_Connection=yes;')
engine = sa.create_engine("mssql+pyodbc:///?odbc_connect=%s" % params,fast_executemany=True, echo=True)
def Load_Data(file_name):
data = pd.read_csv(file_name, skiprows=0)
return data.values.tolist()
BaseGPX = declarative_base()
class GPXFiles(BaseGPX):
#Tell SQLAlchemy what the table name is and if there's any table-specific arguments it should know about
__tablename__ = 'GPXFiles'
__table_args__ = {'schema':'STG'}
#tell SQLAlchemy the name of column and its attributes:
GPXFile_ID = Column(BigInteger, primary_key=True, autoincrement=True, nullable=False) #
GPXFile_Name = Column(String, nullable=True)
GPXFile_Contents = Column(String, nullable=True)
#GPXFile_XMLContents = Column(String, nullable=True)
#GPXFile_Route_ID = Column(BigInteger, nullable=True)
# loop through files
# r=root, d=directories, f = files
for r, d, f in os.walk(path):
for file in f:
if fnmatch2.fnmatch2(file, searchstring):
if file.endswith('.gpx'):
print('gpxfile')
# go straight into the STG.GPXFiles table
#Create the session
#GPXFiles.__table__.drop(bind=engine)
GPXFiles.__table__.create(bind=engine, checkfirst=True) # if the table exists, it is dropped (not using checkfirts=true)
session = sessionmaker(bind=engine)
#print(session)
session.configure(bind=engine)
s = session()
try:
data = Load_Data(os.path.join(r, file))
print (file)
print (data)
record = GPXFiles(**{
'GPXFile_Name' : file,
'GPXFile_Contents' : data
})
s.add(record) #Add all the records
s.commit() #Attempt to commit all the records
except Exception as e:
print(e)
s.rollback() #Rollback the changes on error
s.close() #Close the connection
continue
elif file.endswith('.gpx.gz'):
# print('a GZ gpxfile')
# unzip file first, then get the file into the STG.GPXFiles table
continue
elif file.endswith('.csv'):
# the only file we really need is the activities.csv file
# the columns are
continue
else:
continue
# move file to archive folder at same level as source folder
# first check folder exist, if not, then create it
continue
#conn.close
# now that this is done, we need to run the stored procedures to get the data from the staging tables into the production conformed tables
# first to brng the data from staging into conformed area
# then run a bunch of procs to update some of th missing attributes
# don't forget to clean up in some way
Целевая таблица определяется следующим образом:
USE [Tracks]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [STG].[GPXFiles](
[GPXFile_ID] [bigint] NOT NULL,
[GPXFile_Name] [nvarchar](max) NULL,
[GPXFile_Contents] [nvarchar](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
Вот пример файла (файл gpx):
<?xml version="1.0" encoding="UTF-8"?>
<gpx creator="Somedevice" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" version="1.1" xmlns="http://www.topografix.com/GPX/1/1">
<metadata>
<time>2014-10-04T08:13:37Z</time>
</metadata>
<trk>
<name>My Activity</name>
<type>9</type>
<trkseg>
<trkpt lat="55.9753110" lon="-3.1798280">
<ele>14.8</ele>
<time>2014-10-04T08:13:37Z</time>
</trkpt>
<trkpt lat="55.9749420" lon="-3.1812950">
<ele>15.2</ele>
<time>2014-10-04T08:14:57Z</time>
</trkpt>
</trkseg>
</trk>
</gpx>
Я знаю соединение с базой данных работает, потому что мне удается загрузить файл CSV в другую таблицу в том же файле py
Вот ошибка, которую я получаю (в основном неверный тип данных) - я изменил тип в целевой table to varchar, nvarchar, xml et c безрезультатно. Я не могу найти нужную комбинацию для получения файла в
Вывод в окне вывода (Visual Studio 2019):
2020-02-13 21: 29: 50,272 INFO sqlalchemy.engine.base.Engine SELECT CAST (SERVERPROPERTY ('ProductVersion') AS VARCHAR) 2020-02-13 21: 29: 50,273 INFO sqlalchemy.engine.base.Engine () 2020-02-13 21: 29: 50,275 INFO sqlalchemy.engine.base.Engine SELECT имя_схемы () 2020-02-13 21: 29: 50,275 INFO sqlalchemy.engine.base.Engine () 2020-02-13 21: 29: 50,276 INFO sqlalchemy.engine.base.Engine ВЫБЕРИТЕ CAST («тестовый возврат возвращается» КАК VARCHAR (60)) AS anon_1 2020-02-13 21: 29: 50,277 INFO sqlalchemy.engine.base.Engine () 2020-02-13 21: 29: 50,278 INFO sqlalchemy.engine .base.Engine SELECT CAST («возвращает тест Unicode» AS NVARCHAR (60)) AS anon_1 2020-02-13 21: 29: 50,278 INFO sqlalchemy.engine.base.Engine () 2020-02-13 21: 29: 50,282 ИНФОРМАЦИЯ sqlalchemy.engine.base.Engine SELECT [INFORMATION_SCHEMA]. [COLUMNS]. [TABLE_SCHEMA], [INFORMATION_SCHEMA]. [COLUMNS]. [TABLE_NAME], [INFORMATION_SCHEMA] [[COLUMNS]. [COLUMNN.] [COLUMNS.] [COLUMNS. КОЛОННЫ. . [NUMERIC_PRECISION], [INFORMATION_SCHEMA]. [COLUMNS]. [NUMERIC_SCALE], [INFORMATION_S CHEMA. AS NVARCHAR (макс.) И [INFORMATION_SCHEMA]. [COLUMNS]. [TABLE_SCHEMA] = CAST (? AS NVARCHAR (макс.)) 2020-02-13 21: 29: 50,282 INFO sqlalchemy.engine.base.Engine ('GPXFiles' , 'STG') 2020-02-13 21: 29: 50,289 INFO sqlalchemy.engine.base.Engine BEGIN (неявный) 2020-02-13 21: 29: 50,291 INFO sqlalchemy.engine.base.Engine ВСТАВЬТЕ INTO [STG] . [GPXFiles] ([GPXFile_Name], [GPXFile_Contents]) OUTPUT вставлен. [GPXFile_ID] ЗНАЧЕНИЯ (?,?) 2020-02-13 21: 29: 50,291 INFO sqlalchemy.engine.base.Engine ('203008969.gpx', [[''], ['
15,2'], ['2014-10-04T08: 14: 57Z'], ['
'], [''], [''], ['' ]]) 2020-02-13 21: 29: 50,295 INFO sqlalchemy.engine.base.Engine ROLLBACK (pyodb c .Error) ('HY004', '[HY004] [Microsoft] [ODB C SQL Драйвер сервера] Неверный SQL тип данных (0) (SQLBindParameter) ') [SQL: INSERT INTO [STG]. [GPXFiles] ([GPXFile_Name], [GPXFile_Contents]) OUTPUT вставлен. [GPXFile_ID] ЗНАЧЕНИЯ (?, ?)] [параметры: ('203008969.gpx', [[''], ['
15,2'], ['2014-10-04T08: 14: 57Z'], ['
'], [''], [''], ['']])] (Справочная информация об этой ошибке: http://sqlalche.me/e/dbapi)
Любые предложения приветствуются.