将阵列插入数据库

时间:2019-01-25 20:40:37

标签: python arrays python-2.7 sqlite

我试图编写一个通用函数,该函数会将一行数据插入数据库的表中,但是我试图编写一个未知长度的数组。我的目标是能够在任何程序中调用此函数,并将任意长度的数据行写入表中(假设表和数组的长度相同。

我尝试添加数组,就像它是数据的奇异部分一样。

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 :(得分:0)

SQLite不支持数组-您必须使用','。join()转换为TEXT才能将数组项连接为单个字符串并传递该字符串。

来源:SQLite网站 https://www.sqlite.org/datatype3.html

答案 1 :(得分:0)

我不是Python程序员,但是我从事SQL已有很长时间了。我什至写了自己的ORM。我的建议是不要编写自己的SQL查询生成器。有许多微妙的问题,尤其是安全性问题。我在下面详细说明其中的一些。

请使用完善的SQL查询生成器或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语句中天真地使用时会使查询执行其他操作。像Little Bobby Tables

尽管?可以防止SQL注入值,但仍然可以通过列名进行注入。不能保证列名可以信任。也许它们来自网络表单的参数?

Protecting table and column names is complicated,容易出错。

您编写的SQL越多,就越容易受到注入攻击。

您必须为其他所有代码编写代码。

好的,您已经完成insert。现在update吗? select?不要忘记子查询,分组依据,联合,联接...

如果要编写SQL查询构建器,那就太好了!相反,如果您有使用SQL的工作要做,那么编写另一个SQL查询构建器也不是您的工作。

其他人都很难理解。

任何给定的Python程序员都有很大的机会知道SQLAlchemy的工作方式,如果没有,则有很多教程和文档。他们没有机会知道您的自家推出的SQL函数,因此您必须编写所有教程和文档。

答案 2 :(得分:0)

在没有争论的需求的情况下,您不应尝试编写自己的ORM。您将遇到很多问题,例如,这里有25个not to的简短原因。

请使用任何经过验证的流行ORM。我建议使用SQLAlchemy作为Django之外的工具。使用它,您可以映射值的字典以将其插入到模型中,就像insert(schema_name).values(**dict_name)(这是插入/更新的example)一样。

答案 3 :(得分:-1)

将功能更改为此:

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()