Error while doing UPSERT in Sqlite 3.34 - Error: near "DO": syntax error
Error while doing UPSERT in Sqlite 3.34 - Error: near "DO": syntax error
我正在尝试将每日 CSV 加载文件加载到 main
table 中,以便插入所有新记录并更新所有现有记录。为此,我正在使用 Sqlite 的 UPSERT
功能。
这是我的 shell 脚本。
LOAD_FILE="/tmp/main.csv"
LOAD_TABLE="tbl_tmp_main"
MAIN_TABLE="tbl_main"
COLUMNS="t_id, t_col1, t_col2"
CREATE_TABLE_QUERY="DROP TABLE IF EXISTS $LOAD_TABLE; CREATE TABLE $LOAD_TABLE AS SELECT $COLUMNS FROM $MAIN_TABLE WHERE false"
LOAD_TABLE_QUERY=".separator ','\n.import '$LOAD_FILE' $LOAD_TABLE"
UPSERT_TABLE_QUERY="
INSERT INTO $MAIN_TABLE($COLUMNS) SELECT $COLUMNS FROM $LOAD_TABLE
ON CONFLICT(t_id) DO UPDATE
SET
t_col1 = excluded.t_col1,
t_col2 = excluded.t_col2
;
"
echo ""
echo "$CREATE_TABLE_QUERY" | sqlite3 mydatabase.sqlite3 # <-- This works
echo "[INFO] Temporary Table Created."
echo "$LOAD_TABLE_QUERY" | sqlite3 mydatabase.sqlite3 # <-- This works
echo "[INFO] Data Loaded into Temporary Table."
echo "$UPSERT_TABLE_QUERY" | sqlite3 mydatabase.sqlite3 # <-- This errors out
echo "[INFO] Records Inserted/Updated."
echo ""
这里是错误。
Error: near line 2: near "DO": syntax error
我试图检查 documentation,但我不确定上面的查询有什么问题。有人可以指出为什么它不起作用。
这是我的 sqlite 版本
-> sqlite3 --version
3.34.1 2021-01-20 14:10:07 10e20c0b43500cfb9bbc0eaa061c57514f715d87238f4d835880cd846b9ebd1f
错误是由于文档中提到的 Parsing Ambiguity
。您需要添加 WHERE true
作为 SELECT 子句的一部分,这应该可以修复它。
这是您更新后的 UPSERT 查询。
INSERT INTO $MAIN_TABLE($COLUMNS) SELECT $COLUMNS FROM $LOAD_TABLE WHERE true
-- ^^^^^^^^^^
ON CONFLICT(t_id) DO UPDATE
SET
t_col1 = excluded.t_col1,
t_col2 = excluded.t_col2
;
这是 Docs 中的部分。
Parsing Ambiguity
When the INSERT statement to which the UPSERT is attached takes its values from a SELECT statement, there is a potential parsing ambiguity. The parser might not be able to tell if the "ON" keyword is introducing the UPSERT or if it is the ON clause of a join. To work around this, the SELECT statement should always include a WHERE clause, even if that WHERE clause is just "WHERE true".
Ambiguous use of ON:
INSERT INTO t1 SELECT * FROM t2
ON CONFLICT(x) DO UPDATE SET y=excluded.y;
Ambiguity resolved using a WHERE clause:
INSERT INTO t1 SELECT * FROM t2 WHERE true
ON CONFLICT(x) DO UPDATE SET y=excluded.y;
我正在尝试将每日 CSV 加载文件加载到 main
table 中,以便插入所有新记录并更新所有现有记录。为此,我正在使用 Sqlite 的 UPSERT
功能。
这是我的 shell 脚本。
LOAD_FILE="/tmp/main.csv"
LOAD_TABLE="tbl_tmp_main"
MAIN_TABLE="tbl_main"
COLUMNS="t_id, t_col1, t_col2"
CREATE_TABLE_QUERY="DROP TABLE IF EXISTS $LOAD_TABLE; CREATE TABLE $LOAD_TABLE AS SELECT $COLUMNS FROM $MAIN_TABLE WHERE false"
LOAD_TABLE_QUERY=".separator ','\n.import '$LOAD_FILE' $LOAD_TABLE"
UPSERT_TABLE_QUERY="
INSERT INTO $MAIN_TABLE($COLUMNS) SELECT $COLUMNS FROM $LOAD_TABLE
ON CONFLICT(t_id) DO UPDATE
SET
t_col1 = excluded.t_col1,
t_col2 = excluded.t_col2
;
"
echo ""
echo "$CREATE_TABLE_QUERY" | sqlite3 mydatabase.sqlite3 # <-- This works
echo "[INFO] Temporary Table Created."
echo "$LOAD_TABLE_QUERY" | sqlite3 mydatabase.sqlite3 # <-- This works
echo "[INFO] Data Loaded into Temporary Table."
echo "$UPSERT_TABLE_QUERY" | sqlite3 mydatabase.sqlite3 # <-- This errors out
echo "[INFO] Records Inserted/Updated."
echo ""
这里是错误。
Error: near line 2: near "DO": syntax error
我试图检查 documentation,但我不确定上面的查询有什么问题。有人可以指出为什么它不起作用。
这是我的 sqlite 版本
-> sqlite3 --version
3.34.1 2021-01-20 14:10:07 10e20c0b43500cfb9bbc0eaa061c57514f715d87238f4d835880cd846b9ebd1f
错误是由于文档中提到的 Parsing Ambiguity
。您需要添加 WHERE true
作为 SELECT 子句的一部分,这应该可以修复它。
这是您更新后的 UPSERT 查询。
INSERT INTO $MAIN_TABLE($COLUMNS) SELECT $COLUMNS FROM $LOAD_TABLE WHERE true
-- ^^^^^^^^^^
ON CONFLICT(t_id) DO UPDATE
SET
t_col1 = excluded.t_col1,
t_col2 = excluded.t_col2
;
这是 Docs 中的部分。
Parsing Ambiguity
When the INSERT statement to which the UPSERT is attached takes its values from a SELECT statement, there is a potential parsing ambiguity. The parser might not be able to tell if the "ON" keyword is introducing the UPSERT or if it is the ON clause of a join. To work around this, the SELECT statement should always include a WHERE clause, even if that WHERE clause is just "WHERE true".
Ambiguous use of ON:
INSERT INTO t1 SELECT * FROM t2 ON CONFLICT(x) DO UPDATE SET y=excluded.y;
Ambiguity resolved using a WHERE clause:
INSERT INTO t1 SELECT * FROM t2 WHERE true ON CONFLICT(x) DO UPDATE SET y=excluded.y;