Вставка массивов в базы данных - PullRequest
0 голосов
/ 25 января 2019

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

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

import sqlite3
def add2Db(dbName, tableName, data):
    connection = sqlite3.connect(dbName)
    cur = connection.cursor()
    cur.execute("INSERT INTO "+ tableName +" VALUES (?)", (data))
    connection.commit()
    connection.close()

add2Db("items.db", "allItems", (1, "chair", 5, 4))

Это просто вылетает и выдает ошибку, говоря, что у него 4 столбца, но было передано только одно значение.

Ответы [ 4 ]

0 голосов
/ 26 января 2019

Вы не должны пытаться писать свои собственные ORM без аргументированной необходимости.У вас будет много проблем, например вот 25 быстрых причин , а не .

Вместо этого используйте любую популярную форму, которая доказана.Я рекомендую использовать SQLAlchemy для выхода за пределы Django.Используя его, вы можете отобразить набор значений, чтобы вставить его в модель, как insert(schema_name).values(**dict_name) (вот пример вставки / обновления).

0 голосов
/ 26 января 2019

SQLite не поддерживает массивы - вы должны преобразовать в текст, используя ','. Join (), чтобы объединить элементы массива в одну строку и передать это.

Источник: веб-сайт SQLite https://www.sqlite.org/datatype3.html

0 голосов
/ 26 января 2019

Я не программист на Python, но я давно занимаюсь SQL.Я даже написал свой собственный ORM.Мой совет: не пишите свой собственный конструктор запросов SQL.Существует множество тонких проблем, особенно проблем безопасности.Ниже я подробно остановлюсь на некоторых из них.

Вместо этого используйте хорошо известный SQL Query Builder или ORM.Они уже занимались этими вопросами.Вот пример использования SQLAlchemy .

from datetime import date
from sqlalchemy import create_engine, MetaData

# Connect to the database with debugging on.
engine = create_engine('sqlite:///test.sqlite', echo=True)
conn = engine.connect()

# Read the schemas from the database
meta = MetaData()
meta.reflect(bind=engine)

# INSERT INTO users (name, birthday, state, country) VALUES (?, ?, ?, ?)
users = meta.tables['users']
conn.execute(
    users.insert().values(name="Yarrow Hock", birthday=date(1977, 1, 23), state="NY", country="US")
)

SQLAlchemy может выполнять весь диапазон операций SQL и будет работать с различными вариантами SQL.Вы также получаете тип безопасности.

conn.execute(
    users.insert().values(name="Yarrow Hock", birthday="in the past", state="NY", country="US")
)

sqlalchemy.exc.StatementError: (exceptions.TypeError) SQLite Date type only accepts Python date objects as input. [SQL: u'INSERT INTO users (name, birthday, state, country) VALUES (?, ?, ?, ?)']

insert into table values (...) зависит от порядка определения столбцов

Это зависит от порядка столбцов, определенных в схеме.Это оставляет две проблемы.Во-первых, это проблема читабельности.

add2Db(db, 'some_table', (1, 39, 99, 45, 'papa foxtrot', 0, 42, 0, 6)

Что это значит?Читатель не может сказать.Они должны копаться в схеме и подсчитывать столбцы, чтобы выяснить, что означает каждое значение.

Во-вторых, это проблема технического обслуживания.Если по какой-либо причине схема изменяется и порядок столбцов не является точно одинаковым, это может привести к чрезвычайно трудным поискам ошибок.Например ...

create table users ( name text, birthday date, state text, country text );
vs
create table users ( name text, birthday date, country text, state text );

add2Db(db, 'users', ('Yarrow Hock', date(1977, 1, 23), 'NY', 'US'));

Эта вставка будет молча "работать" с любым порядком столбцов.

Это можно исправить, передав словарь и используя ключи для имен столбцов.

add2Db(db, 'users', (name="Yarrow Hock", birthday=date(1977, 1, 23), state="NY", country="US"));

Затем мы создадим запрос, подобный следующему:

insert into users
    (name, birthday, state, country)
values (?, ?, ?, ?)

Это приводит к следующей и гораздо более серьезной проблеме.

Атака SQL-инъекцией

Теперь это открывает новую проблему.Если мы просто вставим имена таблиц и столбцов в запрос, который оставляет нас открытыми для одной из самых распространенных дыр в безопасности, SQL Injection Attack .Вот где кто-то может создать значение, которое при наивном использовании в выражении SQL заставляет запрос делать что-то еще.Как Маленькие таблицы Бобби .

Хотя ? защищает от SQL-инъекций для значений, все еще возможно вводить через имена столбцов.Там нет гарантии, что имена столбцов можно доверять.Может быть, они пришли из параметров веб-формы?

Защита имен таблиц и столбцов сложна и легко ошибиться.

Чем большеSQL вы пишете, тем более вероятно, что вы уязвимы для инъекционной атаки.

Вы должны написать код для всего остального.

Хорошо, вы сделали insert.Сейчас update?select?Не забывайте о подзапросах, группировании, объединениях, объединениях ...

Если вы хотите написать конструктор SQL-запросов, круто!Если вместо этого у вас есть работа с использованием SQL, написание еще одного компоновщика SQL-запросов не ваша работа.

Труднее понять другим.

Есть хороший шанс, что любойданный программист на Python знает, как работает SQLAlchemy, и есть множество руководств и документации, если они этого не делают.У них нет шансов узнать о ваших собственных функциях SQL, и вы должны написать все учебные пособия и документы.

0 голосов
/ 25 января 2019

Измените свою функцию следующим образом:

def add2Db(dbName, tableName, data):
    num_qs = len(data)
    qm = ','.join(list('?' * num_qs))

    query = """
        INSERT INTO {table}
        VALUES ({qms})
             """.format(table=tableName,
                        qms=qm)
    connection = sqlite3.connect(dbName)
    cur = connection.cursor()
    cur.execute(query, data)
    connection.commit()
    connection.close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...