Синтаксическая ошибка PyODBC при попытке вставки CSV-файла

#sql #sql-server #pyodbc

#sql #sql-сервер #pyodbc

Вопрос:

 for fileName in fileNames:
   with open(fileName, mode="rt", encoding="utf-8", newline="") as csvfile:
        csvFile = csv.reader(csvfile, delimiter=',')
        header = next(csvFile)
        headers = map((lambda x: x.strip()), header)
        insert = 'INSERT INTO TEST ('.format(tableChoice)   ', '.join(headers)   ') VALUES '
        for row , record in enumerate(csvFile, start=1):
            values = map((lambda x: "'" x.strip() "'"), record)

            myCursor.execute(insert  '('  ', '.join(values)  ');' )
            cnxn.commit()
  

Я получаю приведенную ниже ошибку, когда дохожу до execute строки в скрипте. Мне просто нужны данные, извлеченные из csv, для вставки в базу данных, строка за строкой. Кто-нибудь знает, что вызывает ошибку?

Ошибка программирования: (‘42000’, «[42000] [ Microsoft] [Драйвер ODBC SQL Server] [SQL Server] Неправильный синтаксис рядом с ‘-‘. (102) (SQLExecDirectW)»)

Редактировать:

Строка запроса SQL выглядит следующим образом:

 INSERT INTO TEST (this, that, those) VALUES ('1', '11', '111');
INSERT INTO TEST (this, that, those) VALUES ('2', '22', '222');
INSERT INTO TEST (this, that, those) VALUES ('3', '33', '333');
  

Комментарии:

1. Покажите нам окончательный SQL, поскольку он передается на сервер.

2. Отредактированное исходное сообщение

3. Похоже, вы должны разделять имена столбцов, если в них есть дефисы ( - ). Или, что еще лучше, измените имена ваших объектов, чтобы их не нужно было определять разделителями в первую очередь.

4. При создании списка имен столбцов вы должны использовать ", ".join([f"[{x}]" for x in headers])

5. Кроме того, вам действительно следует параметризовать свой запрос, и если ваши CSV-файлы содержат более нескольких десятков строк, вы также должны использовать myCursor.fast_executemany = True

Ответ №1:

Вероятно, проблема связана со специальными символами в именах столбцов, например, - которые требуют заключения в квадратные скобки для экранирования в SQL Server. Кроме того, рассмотрите возможность использования согласованного форматирования строк в Python и csv.DictReader создания параметризованного запроса, за которым следует executemany для вставки:

 for fileName in fileNames:
   with open(fileName, mode="rt", encoding="utf-8", newline="") as csvfile:
       reader = csv.DictReader(f)
       data = [row for row in reader]

       # BUILD SQL WITH [...] ESCAPED COLUMNS AND ? PARAM PLACEHOLDERS
       sql = "INSERT INTO [Test] ([{cols}]) VALUES ({prms})"
       sql = sql.format(cols="], [".join(map(lambda x: x.strip(), data[0].keys())), 
                        prms=", ".join(['?'] * len(data[0])))    
 
       # APPEND ALL ROWS AND BIND PARAMS
       myCursor.executemany(sql, [list(d.values()) for d in data])
       cnxn.commit()