Python 使用包含唯一约束的实际值创建SQLITE表的最佳方法是什么?
我试图理解处理SQLITE3中浮点比较的最佳方法。一般来说,我理解测试浮动是否相等是一种不好的做法。但是,我不确定在SQLITE关系数据库中如何执行此操作 根据定义,对表中的行使用唯一约束是为了测试相等性。那么,在处理真实数据类型时,这是一种糟糕的做法吗 如果我想选择唯一的行,只知道真正的值,我应该怎么做 我在SQLITE3中有下表:Python 使用包含唯一约束的实际值创建SQLITE表的最佳方法是什么?,python,sql,database,sqlite,data-structures,Python,Sql,Database,Sqlite,Data Structures,我试图理解处理SQLITE3中浮点比较的最佳方法。一般来说,我理解测试浮动是否相等是一种不好的做法。但是,我不确定在SQLITE关系数据库中如何执行此操作 根据定义,对表中的行使用唯一约束是为了测试相等性。那么,在处理真实数据类型时,这是一种糟糕的做法吗 如果我想选择唯一的行,只知道真正的值,我应该怎么做 我在SQLITE3中有下表: CREATE TABLE nodes( node_id INTEGER PRIMARY KEY, node_number INTEGER,
CREATE TABLE nodes(
node_id INTEGER PRIMARY KEY,
node_number INTEGER,
x REAL,
y REAL,
z REAL,
UNIQUE(node_number, x, y, z)
);
对于表插入,我执行以下操作:
INSERT OR IGNORE INTO
nodes(node_number, x, y, z)
VALUES
(?, ?, ?, ?);
SELECT
node_id
FROM
nodes
WHERE
node_number = ?
AND
x = ?
AND
y = ?
AND
z = ?;
要查找后续插入的节点\u id,请执行以下操作:
INSERT OR IGNORE INTO
nodes(node_number, x, y, z)
VALUES
(?, ?, ?, ?);
SELECT
node_id
FROM
nodes
WHERE
node_number = ?
AND
x = ?
AND
y = ?
AND
z = ?;
一种选择可能是将值存储为格式化字符串,并对其强制唯一约束
CREATE TABLE nodes(
node_id INTEGER PRIMARY KEY,
node_number INTEGER,
x TEXT,
y TEXT,
z TEXT,
UNIQUE(node_number, x, y, z)
);
其中,浮点值存储在:
CREATE TABLE node_values(
node_value_id INTEGER PRIMARY KEY,
node_id REFERENCES nodes(node_id),
x REAL,
y REAL,
z REAL,
UNIQUE(node_id)
);
插入内容可能如下所示:
蟒蛇
...
node_values = [
(nnum1, x1, y1, z1),
(nnum2, x2, y2, z2),
...
]
sql_insert_text_vals = """
INSERT OR IGNORE INTO
nodes(node_number, x, y, z)
VALUES
(?, ?, ?, ?);
"""
text_values = [
(node_number, f'{xval:.10f}', f'{yval:.10f}', f'{zval:.10f}')
for node_number, xval, yval, zval
in node_values
]
cursor.executemany(sql_insert_text_vals, text_values)
sql_query = """
SELECT
node_id
VALUES
(?, ?, ?, ?);
"""
node_ids = [
cursor.fetchone()[0]
for value in text_values
for cursor.execute(sql_query, value)
]
sql_insert_node_values = """
INSERT OR IGNORE INTO
node_values(node_id, x, y, z)
VALUES
(?, ?, ?, ?);
"""
real_values = [
(node_id, xval, yval, zval)
for node_id, (node_number, xval, yval, zval)
in zip(node_ids, node_values)
]
cursor.executemany(sql_insert_node_values, real_values)
这样更好吗?一个选项可能是将值存储为格式化字符串,并对其强制唯一约束
CREATE TABLE nodes(
node_id INTEGER PRIMARY KEY,
node_number INTEGER,
x TEXT,
y TEXT,
z TEXT,
UNIQUE(node_number, x, y, z)
);
其中,浮点值存储在:
CREATE TABLE node_values(
node_value_id INTEGER PRIMARY KEY,
node_id REFERENCES nodes(node_id),
x REAL,
y REAL,
z REAL,
UNIQUE(node_id)
);
插入内容可能如下所示:
蟒蛇
...
node_values = [
(nnum1, x1, y1, z1),
(nnum2, x2, y2, z2),
...
]
sql_insert_text_vals = """
INSERT OR IGNORE INTO
nodes(node_number, x, y, z)
VALUES
(?, ?, ?, ?);
"""
text_values = [
(node_number, f'{xval:.10f}', f'{yval:.10f}', f'{zval:.10f}')
for node_number, xval, yval, zval
in node_values
]
cursor.executemany(sql_insert_text_vals, text_values)
sql_query = """
SELECT
node_id
VALUES
(?, ?, ?, ?);
"""
node_ids = [
cursor.fetchone()[0]
for value in text_values
for cursor.execute(sql_query, value)
]
sql_insert_node_values = """
INSERT OR IGNORE INTO
node_values(node_id, x, y, z)
VALUES
(?, ?, ?, ?);
"""
real_values = [
(node_id, xval, yval, zval)
for node_id, (node_number, xval, yval, zval)
in zip(node_ids, node_values)
]
cursor.executemany(sql_insert_node_values, real_values)
这更好吗?在SQLite中,检查约束不能有子查询,因此如果您想在SQLite本身中执行邻近性检查,则必须使用触发器,例如:
CREATE TRIGGER notequal
BEFORE INSERT ON test
BEGIN
SELECT CASE
WHEN (EXISTS (SELECT r FROM test WHERE abs(NEW.r - r) < 0.1))
THEN RAISE (ABORT,'Value too close to an existing value')
END;
END;
当然,您也希望在更新中使用相同的内容。在SQLite中,检查约束不能有子查询,因此如果您希望在SQLite本身中执行近似检查,则必须使用触发器,例如:
CREATE TRIGGER notequal
BEFORE INSERT ON test
BEGIN
SELECT CASE
WHEN (EXISTS (SELECT r FROM test WHERE abs(NEW.r - r) < 0.1))
THEN RAISE (ABORT,'Value too close to an existing value')
END;
END;
当然,对于更新,您也需要相同的内容。您可以检查类似于absa-b>=0.01的内容。也许您可以定义一个自定义https://docs.sqlalchemy.org/en/13/core/constraints.htmlsqlalchemy.schema.UniqueConstraint 并覆盖uuu eq uuu,但是你必须询问SQLAlchemy的专业人士,你提供的链接中的一个建议是使用十进制类型。然而,当我阅读Sqlite文档时,似乎Sqlite只是将其转化为一个真实的数据库引擎,而其他数据库引擎的工作方式与Python的Decimal类类似。我想知道我是否可以只乘以所需的精度10^9,然后将其存储为整数?对我来说,这一切似乎比它应该的更骇人听闻。您可以检查absa-b>=0.01之类的内容,或者您可以定义一个自定义https://docs.sqlalchemy.org/en/13/core/constraints.htmlsqlalchemy.schema.UniqueConstraint 并覆盖_eq _,但您必须询问SQLAlchemy专业人士。您提供的链接中的一个建议是使用十进制类型。然而,当我阅读Sqlite文档时,似乎Sqlite只是将其转化为一个真实的数据库引擎,而其他数据库引擎的工作方式与Python的Decimal类类似。我想知道我是否可以只乘以所需的精度10^9,然后将其存储为整数?这一切对我来说似乎比应该的更骇人。我不知道触发器。我想你应该把0.1改成期望的精度水平?我不知道触发器。我想您应该将0.1更改为所需的精度级别?