Python SQLite 插入动态列或使用默认值

Python SQLite insert with dynamic columns or use DEFAULT value

我正在使用 flask-restful 并且用户可以 post 一些必需的和一些可选的数据,我想用这些数据制作 SQLite 插入语句。问题是我不想通过对列名使用变量并检查哪个参数是 None 以及哪个参数有一些数据来破坏 sql 语句。我希望我可以只使用所有列,当 arg2 或 arg3 为 None 时,数据库将使用列默认值。遗憾的是我收到消息 NOT NULL constraint failed: mytable.col1。使用我的方法从 table 创建中删除 NOT NULL 将在使用我的语句时插入 NULL。

是否有明确的方法告诉 SQLite 使用其默认值?

如果不是,是否有更优雅的方式来获取默认值而不是执行某些 table 模式查询?

如果没有并且没有其他解决方案存在,那么什么是最有效的方法来消除 sql 语句?

parser_post = reqparse.RequestParser()
parser_post.add_argument('arg1', type=str, required=True)
parser_post.add_argument('arg2', type=str)
parser_post.add_argument('arg3', type=str)
args = parser_post.parse_args()

# ... db init code

cur.execute("insert into mytable (col1, col2, col3) values (?, ?, ?)", 
(args['arg1'], args['arg2'], args['arg3']))

table 是这样创建的:

sql = """CREATE TABLE mytable (
    PK_id       INTEGER PRIMARY KEY AUTOINCREMENT,
    col1        INTEGER NOT NULL,
    col2        TEXT DEFAULT "global" NOT NULL,
    col3        TEXT DEFAULT "global" NOT NULL)"""
cursor.execute(sql)

一种回退到数据库端默认值的方法是不为插入中的特定列提供数据。

在这种情况下,服务器将为该列插入默认值。如果您没有在 CREATE TABLE(或更高版本的 ALTER TABLE)中指定默认值,则默认值为 NULL(对应于 Python None)。

但是,由于 col2 确实 有一个数据库指定的默认值,通过 col2 TEXT DEFAULT "global" NOT NULL,然后在插入中不指定 col2 反而会导致 sqlite使用 "global"。同上 col3.

您可以动态构建查询,以排除具有 None 的列,只要您谨慎处理查询字符串中的内容即可。

def prep_qry(args, colnames):
    """this query is secure as long as `colnames` contains trusted data
    standard parametrized query mechanism secures `args`"""

    binds,use = [],[]

    for colname, value in zip(colnames,args):
        if value is not None:
            use.extend([colname,","])
            binds.extend(["?",","])


    parts = ["insert into mytable ("]
    use = use[:-1]
    binds = binds[:-1]
    
    parts.extend(use)
    parts.append(") values(")
    parts.extend(binds)
    parts.append(")")

    qry = " ".join(parts)

    return qry, tuple([v for v in args if not v is None])

print(prep_qry([1,None,3], ["col1", "col2", "col3"]))
print(prep_qry([1,2,3], ["col1", "col2", "col3"]))

输出:

('insert into mytable ( col1 , col3 ) values( ? , ? )', (1, 3))
('insert into mytable ( col1 , col2 , col3 ) values( ? , ? , ? )', (1, 2, 3))