如何处理 SQLite 的缺失功能:disable triggers
?
我没有存储特定表的触发器名称。
例如,如何删除所有触发器?
你会怎么做?
如何处理 SQLite 的缺失功能:disable triggers
?
我没有存储特定表的触发器名称。
例如,如何删除所有触发器?
你会怎么做?
我编写了一个非常简单的扩展函数来将布尔值设置为真或假。
以及检索此值的函数 (GetAllTriggersOn())。
使用此功能,我可以定义所有触发器,例如:
CREATE TRIGGER tr_table1_update AFTER UPDATE ON TABLE1 WHEN GetAllTriggersOn()
BEGIN
-- ...
END
所以现在是 2015 年,SQLite 中仍然没有“禁用触发器”。对于移动应用程序,这可能会出现问题——特别是如果它是一个需要离线功能和本地数据的公司应用程序。
即使您没有将每个插入包装在单独的事务中,也可以通过触发器执行来减慢初始数据加载的速度。
我使用 SQLite SQL 相当简单地解决了这个问题。我有一个不参与初始化加载的设置表。它包含键/值对的“列表”。我有一个名为“fireTrigger”的键,其位值为 0 或 1。我拥有的每个触发器都有一个选择值的表达式,如果它等于 1,它会触发触发器,否则不会。
该表达式是对与触发器相关的数据进行评估的任何表达式的补充。例如:
AND 1 = (SELECT val FROM MTSSettings WHERE key = 'fireTrigger')
在简单的干净效果中,这使我可以通过简单UPDATE
的设置表来禁用/启用触发器
SQLite 将模式(元)信息存储在内置sqlite_master
表中。
要获取可用触发器的列表,请使用以下查询:
SELECT name FROM sqlite_master
WHERE type = 'trigger' -- AND tbl_name = 'a_table_name'
在您的数据库中设置一个标志并在触发器 WHEN 条件中使用它。
假设您想在插入后在“客户”表上创建触发器。您已经创建了一个带有 TINYINT“triggers_on”字段的表“trigger_settings” - 这是您的标志。然后,如果要关闭过滤器,可以将该字段设置为 0,如果要重新打开过滤器,则可以将该字段设置为 1。
然后,您使用检查“triggers_on”字段的 WHEN 条件创建过滤器。
例如:
CREATE TRIGGER IF NOT EXISTS log_client_data_after_insert
AFTER INSERT
ON [clients]
WHEN (SELECT triggers_on FROM trigger_settings)=1
BEGIN
your_statement
END;
也许您可以制作一个存储过程来删除和创建它们。这对你有好处吗?
扩展其他答案这就是我的做法。考虑到这将禁用数据库中所有表的所有触发器,除了一些然后由spatialite
SQLITE_FILE=/tmp/my.sqlite
# Define output sql files as variables
CREATE_TRIGGER_SQL=/tmp/create_triggers.sql
DROP_TRIGGER_SQL=/tmp/drop_triggers.sql
## Dump CREATE TRIGGER statements to a file ##
# To wrap statements in a transaction
echo -e "BEGIN;\n\n" > "${CREATE_TRIGGER_SQL}"
# `SELECT sql` does not output semicolons, so we must concatenate them
sqlite3 -bail "${SQLITE_FILE}" "SELECT sql || ';' FROM sqlite_master WHERE type = 'trigger' AND (name NOT LIKE 'gid_%' AND name NOT LIKE 'ggi_%' AND name NOT LIKE 'ggu_%' AND name NOT LIKE 'gii_%' AND name NOT LIKE 'giu_%' AND name NOT LIKE 'vwgcau_%' AND name NOT LIKE 'vtgcau_%' AND name NOT LIKE 'gcau_%' AND name NOT LIKE 'geometry_columns_%' AND name NOT LIKE 'gcfi_%' AND name NOT LIKE 'gctm_%' AND name NOT LIKE 'vtgcfi_%' AND name NOT LIKE 'vwgcfi_%' AND name NOT LIKE 'vtgcs_%' AND name NOT LIKE 'vwgc_%' AND name NOT LIKE 'vtgc_%' AND name NOT LIKE 'gcs_%');" >> "${CREATE_TRIGGER_SQL}"
echo -e "\n\nCOMMIT;" >> "${CREATE_TRIGGER_SQL}"
## Dump DROP TRIGGER statements to a file ##
echo -e "BEGIN;\n\n" > "${DROP_TRIGGER_SQL}"
sqlite3 -bail "${SQLITE_FILE}" "SELECT 'DROP TRIGGER ' || name || ';' FROM sqlite_master WHERE type = 'trigger' AND (name NOT LIKE 'gid_%' AND name NOT LIKE 'ggi_%' AND name NOT LIKE 'ggu_%' AND name NOT LIKE 'gii_%' AND name NOT LIKE 'giu_%' AND name NOT LIKE 'vwgcau_%' AND name NOT LIKE 'vtgcau_%' AND name NOT LIKE 'gcau_%' AND name NOT LIKE 'geometry_columns_%' AND name NOT LIKE 'gcfi_%' AND name NOT LIKE 'gctm_%' AND name NOT LIKE 'vtgcfi_%' AND name NOT LIKE 'vwgcfi_%' AND name NOT LIKE 'vtgcs_%' AND name NOT LIKE 'vwgc_%' AND name NOT LIKE 'vtgc_%' AND name NOT LIKE 'gcs_%');" >> "${DROP_TRIGGER_SQL}"
echo -e "\n\nCOMMIT;" >> "${DROP_TRIGGER_SQL}"
## Execute like ##
sqlite3 -bail /"${SQLITE_FILE}" < "${DROP_TRIGGER_SQL}"
# do things
sqlite3 -bail /"${SQLITE_FILE}" < "${CREATE_TRIGGER_SQL}"
扩展 Nick Dandoulakis 的答案,您可以删除所有相关触发器,然后在事务完成之前恢复它们:
BEGIN;
SELECT name, sql FROM sqlite_master WHERE type = 'trigger' AND tbl_name = 'mytable';
-- store all results
-- for each name: DROP TRIGGER $name;
-- do normal work
-- for each sql: execute the SQL verbatim
COMMIT;