5

我正在构建一个供客户自己使用的数据库管理工具,并且在处理更新主键/唯一键的可能性时遇到了一些问题。因此,鉴于更新的数据是由 PHP 脚本逐行传递的,这就是我想出的(从“立即”到“一段时间后”):

  1. 删除/插入而不是更新(糟糕,我现在......):

    DELETE FROM table WHERE unique_key=x;
    DELETE FROM table WHERE unique_key=y;
    INSERT INTO table VALUES (unique_key=y, field=record1), (unique_key=x, field=record2);
    
  2. 更改我的主键/唯一键,然后用修改后的值替换它们:

    UPDATE table SET unique_key=x* WHERE unique_key=x;
    UPDATE table SET unique_key=y* WHERE unique_key=y;
    UPDATE table SET unique_key=y WHERE unique_key=x*;
    UPDATE table SET unique_key=x WHERE unique_key=y*;
    
  3. 将不可修改的 auto_increment 字段“id”添加到我的所有表中,作为代理主键

现在,我正在为所有内容添加“id”字段。其他选择?

4

2 回答 2

1

更新主键不是问题;SQL(和关系模型)中的所有值都应该是可更新的。

问题似乎是交换主键,这

  • 如果您使用代理键对我来说没有意义(因为它们没有意义,因此不需要更新)并且
  • 如果你使用自然键对我来说没有意义,因为这就像用你的交换我的StackOverflow 用户 ID。

向每个表添加“ID”列对您没有帮助。“unique_key”列仍然必须声明为唯一的。添加“ID”列不会改变业务需求。

如果 MySQL 支持延迟约束,您可以交换主键值。(延迟约束是标准 SQL 中的一个特性。)但是 MySQL 不支持该特性。例如,在 PostgreSQL 中,您可以这样做。

create table test (
  unique_key char(1) primary key deferrable initially immediate,
  other_column varchar(15) not null
);

insert into test values 
('x', 'record2'),
('y', 'record1');

begin;
set constraints test_pkey deferred;
update test set unique_key = 'y' where other_column = 'record2';
update test set unique_key = 'x' where other_column = 'record1';
commit;

select * from test;

unique_key  other_column
--
y           record2
x           record1
于 2013-05-08T22:53:50.740 回答
0

您应该能够使用 CASE 表达式来进行这种更新。例如:

UPDATE tbl SET col =
    CASE    WHEN col = 1 THEN 2
            WHEN col = 2 THEN 1
    END
WHERE col IN (1,2);

(未经测试的代码)

于 2013-05-09T19:47:51.797 回答