You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SQLite如何锁定特定列以避免误执行UPDATE操作?

如何锁定表中特定列防止误更新,同时允许修改其他列

当然可以实现这个需求!具体的方案取决于你使用的数据库系统,下面是几个主流数据库的常用做法:

MySQL/MariaDB

场景1:针对特定用户限制更新权限

如果只是想限制某个用户只能修改指定列,可以直接用GRANT语句精准控制权限:

-- 授予用户user1只能更新table1的col2、col3列,禁止修改col1、col4
GRANT UPDATE(col2, col3) ON your_database.table1 TO 'user1'@'localhost';

这样用户执行包含col1或col4的UPDATE语句时会直接报错。

场景2:防止所有用户(包括管理员)误修改敏感列

如果要避免所有人(比如管理员手抖)修改特定列,可以用BEFORE UPDATE触发器来拦截非法修改:

DELIMITER //
CREATE TRIGGER prevent_update_sensitive_cols
BEFORE UPDATE ON table1
FOR EACH ROW
BEGIN
    -- 检查是否修改了col1或col4,如果是则抛出错误
    IF OLD.col1 != NEW.col1 OR OLD.col4 != NEW.col4 THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '禁止修改col1和col4列';
    END IF;
END //
DELIMITER ;

执行UPDATE时如果试图修改col1或col4,触发器会直接终止操作并返回自定义错误信息。

PostgreSQL

PostgreSQL支持更灵活的列级权限控制,同时也可以用触发器兜底:

列级权限控制

直接通过GRANT指定允许更新的列:

-- 授予角色role1只能更新table1的col2、col3列
GRANT UPDATE (col2, col3) ON table1 TO role1;

如果需要收回已有权限,可以先执行:

REVOKE UPDATE ON table1 FROM role1;

再重新授予限定列的权限。

触发器拦截所有用户的非法修改

和MySQL类似,用触发器阻止敏感列被修改:

CREATE OR REPLACE FUNCTION prevent_sensitive_col_update()
RETURNS TRIGGER AS $$
BEGIN
    IF OLD.col1 != NEW.col1 OR OLD.col4 != NEW.col4 THEN
        RAISE EXCEPTION '禁止修改col1和col4列';
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_prevent_sensitive_update
BEFORE UPDATE ON table1
FOR EACH ROW EXECUTE FUNCTION prevent_sensitive_col_update();

SQL Server

权限控制方式

同样可以通过GRANT限制特定用户的更新列:

-- 授予用户user1只能更新table1的col2、col3列
GRANT UPDATE (col2, col3) ON table1 TO user1;

触发器拦截方案

使用INSTEAD OF UPDATE触发器来验证并拦截非法修改:

CREATE TRIGGER tr_prevent_sensitive_col_update
ON table1
INSTEAD OF UPDATE
AS
BEGIN
    -- 检查是否修改了敏感列
    IF UPDATE(col1) OR UPDATE(col4)
    BEGIN
        RAISERROR('禁止修改col1和col4列', 16, 1);
        RETURN;
    END;
    -- 执行合法的更新操作
    UPDATE table1
    SET col2 = inserted.col2, col3 = inserted.col3
    FROM inserted
    WHERE table1.id = inserted.id;
END;

补充说明

  • 权限控制方案适合长期的用户权限管理,而触发器方案适合全局的防误操作(包括管理员)。
  • 如果你用的是其他数据库(比如Oracle),思路类似:要么用列级GRANT,要么用触发器拦截。

内容的提问来源于stack exchange,提问作者Víctor Asem

火山引擎 最新活动