2011-11-17 55 views
0

在用户界面中,我显示account_idaccount_name
用户能够更新account_id以及account_name,并且account_id对用户是唯一的。由于我允许用户更新account_id(组合键),我怎样才能在更新时创建一个where子句?SQL:如何更新复合键?

以下是我的餐桌设计。

CREATE TABLE accounts (
    user_id  VARCHAR2(20) NOT NULL, 
    account_id VARCHAR2(20) NOT NULL, 
    account_name VARCHAR2(20) NOT NULL 
) 

ALTER TABLE accounts ADD CONSTRAINT 
uk_myTable_1 UNIQUE (User_id, account_id) 
+0

虽然这有效,但我都是为了永远不会分享或展示的幕后不可变的钥匙;它消除了外键关系和组合键部分更新的问题。(IE添加一个字段(AccountID,这是PK,并用于FK关系。 – xQbert

+0

@OMGPonies它的Oracle ... – james007

+0

一些想法的饲料:http://programmers.stackexchange.com/questions/8187/should-a- primary-key-be-immutable – xQbert

回答

3

account_iduser_id值保持,直到你改变它们。

因此。如果它开始为user_id 10与account_id 20,并且您将account_id更改为30

UPDATE accounts 
    SET account_id = '30' 
    WHERE account_id = '20' 
     AND user_id = '10'; 

虽然,你保留你的复合键的所有值情况下,上述工程,我所有的,它永远不会共享或显示的幕后不可改变的关键。它消除了外键关系和组合键部分更新的问题。要实现这一点,添加一个字段(AccountID),这是PK,并在FK关系中使用。

或者,Oracle可以通过使用ROWSCN和所有表的无状态环境行相关性来做类似于此的事情。如果仅使用AccountID,则可能遇到的问题是,在多用户环境中,可以让人员对记录1和用户2进行更新以编辑记录1,然后保存;覆盖用户1的更新。这是我提到ROWSCN和ROWDEPENDENCIES的原因。但是,如果您处于状态感知的环境中,这将会过度。

最后,您可以在更新课程之前更改操作的顺序以执行数据库更新。这样你有两个值。

+0

我喜欢你的解决方案,在幕后拥有不变的钥匙......在你的答案部分明确你的观点...... – james007

0
UPDATE accounts 
SET whatevercolumnsyouwantasnormal 
WHERE USER_ID = 'whatever' and ACCOUNT_ID = 'whatever2' 

显然,这将需要你(在新的单独)跟踪原始USER_ID和ACCOUNT_ID,直至发出UPDATE。

如果这是一个Web应用程序(特别是),请务必考虑用户快速连续两次触发此过程的情况。

或者,查看Oracle的RowID。您可以在WHERE子句中使用它,而不是PK列。

+0

更新账户设置account_id ='dummy2'其中user_id ='user1'和account_id ='accountid'因为我更改了UI中的account_id,所以在业务层没有旧的account_id来形成where子句... – james007

+0

GUI中的隐藏字段,用于跟踪组合键。或者您的类需要扩展以保留组合键的值,以便您可以构建where子句...... – xQbert

+0

@ james007您需要跟踪某种方式来识别该行。没有其他办法了。 – mjwills

0

试试这个:

UPDATE accounts SET account_id = New_account,account_name = new_name 
WHERE user_id = Old_id and account_id = old_account_id 
+0

因为我正在改变account_id,我不保留old_account_id ..我足够的灵活性,以改变表设计,如果需要....我需要跟踪old_values?我相信,不是好practive .. – james007

+0

您必须将原始帐户ID存储在某个地方,否则如何查找该记录。我只建议使用旧的帐户ID作为搜索关键字...... – Sparky

+0

我认为他意味着包含信息的类在覆盖数据库之前被覆盖。另一种选择是在您更新课程之前更新数据库。 – xQbert

0

SQL中的工作单元是行,而不是列。

现在不实际运行这一点,但认为

UPDATE accounts 
    SET user_id = account_id, 
     account_id = user_id ; 

会成功交换user_idaccount_id为所有用户。这是因为受到更新影响的所有行(由WHERE子句确定)都会一次全部更新。