При импорте XML содержимого файла в SQL таблицу базы данных сервера с использованием Python происходит сбой из-за ошибки типа данных - PullRequest
0 голосов
/ 14 февраля 2020

Я пытаюсь загрузить файл 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)

Любые предложения приветствуются.

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