[英]SQL: How to update from 'tableA pointing to tableB' to 'tableA poiting to tableC pointing to tableB' without losing existing element relation?
基本上,我想要一Book
介於Line
和User
之間的直接鏈接之間的中間Book
。 Line
元素已經存在,並且不會丟失與相應的已經存在的User
元素的關系,因此需要創建一個默認的Book
元素來處理已經存在的數據。
表是這樣創建的:
User (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(50) NOT NULL
);
Line (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(300),
id_user INT UNSIGNED NOT NULL,
FOREIGN KEY (id_user) REFERENCES User(id)
);
現在,我需要創建一些SQL代碼來生成如下表:
User (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(50) NOT NULL
);
Book (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(300),
id_user INT UNSIGNED NOT NULL,
FOREIGN KEY (id_user) REFERENCES User(id)
);
Line (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(300),
id_book INT UNSIGNED NOT NULL,
FOREIGN KEY (id_book) REFERENCES Book(id)
);
...除了數據已經存在。 所以我有指向用戶元素的Line元素,並且我不能從頭開始創建新表。 因此,我需要SQL代碼來修改現有結構。
基本上,我只希望用戶的書有行,而書的書中沒有行。 並且已經存在的線路可以與所有者用戶建立聯系。 最好的方法是什么?
///////////////////////////////////////////////////// /////
一些樣本數據代表我的數據庫當前的樣子:
Table user(id,username)
- 1, user1
- 2, user2
- 3, user3
Table line(id,title,id_user)
- 1, line1, 1
- 2, line2, 1
- 3, linex, 1
- 4, line1, 2
- 5, liney, 2
輸出應為以下數據庫:
Table user(id,username)
- 1, user1
- 2, user2
- 3, user3
Table book(id,title,id_user)
- 1, 'default', 1
- 2, 'default', 2
- 3, 'default', 3
Table line(id,title,id_book)
- 1, line1, 1
- 2, line2, 1
- 3, linex, 1
- 4, line1, 2
- 5, liney, 2
////////////////////////////////
我的管道當前看起來是什么樣的,我的主要問題是產生最終查詢:
create table book
$sql = "CREATE TABLE IF NOT EXISTS book(
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(300),
id_user INT UNSIGNED NOT NULL,
FOREIGN KEY (id_user) REFERENCES User(id)
); ";
$conn->exec($sql);
//insert default book corresponding to every user
$sql = "INSERT INTO Book(title, id_user) SELECT DISTINCT 'default', id FROM User;";
$conn->exec($sql);
//insert id_book foreign key into Line table pointing to Book table
$sql = "ALTER TABLE Line ADD id_book INT;"
$conn->exec($sql);
//make Line.id_book foreign key pointing to Line.id
$sql="ALTER TABLE Line ADD FOREIGN KEY (id_book) REFERENCES User(id);"
$conn->exec($sql);
//unfinished
$sql = "UPDATE
Line
SET
Line.id_book = Book.id
WHERE
Line.id_user = Book.id_user"
創建表格book
(就像您已經做過的那樣):
CREATE TABLE IF NOT EXISTS book(
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(300),
id_user INT UNSIGNED NOT NULL,
FOREIGN KEY (id_user) REFERENCES User(id)
);
填充新表:
INSERT INTO Book(title, id_user) SELECT 'default', id FROM User;
我從您的代碼中刪除了DISTINCT
,因為id
是主要/唯一的,因此可以確保每條選定的行都是唯一的。
將列id_book
添加到line
表中:
ALTER TABLE Line ADD id_book INT UNSIGNED;
必須為INT UNSIGNED
才能匹配引用的數據類型。
添加外鍵:
ALTER TABLE Line ADD FOREIGN KEY (id_book) REFERENCES book(id);
它應該引用一本書,而不是您的代碼中的用戶。
更新數據(與用戶(第一本)書相關):
UPDATE Line
SET Line.id_book = (
SELECT book.id
FROM book
WHERE book.id_user = Line.id_user
ORDER BY book.id
LIMIT 1
);
刪除line.id_user
列:
-- use "SHOW CREATE TABLE line" to find out the foreign key name
ALTER TABLE Line DROP FOREIGN KEY line_ibfk_1;
ALTER TABLE Line DROP id_user;
http://sqlfiddle.com/#!9/3faa13/1
注意:如果用戶有兩本書或更多本書,那么您不知道哪本書可以與line
鏈接。 在您的問題中,您沒有定義如何處理這種情況。 所以我決定按id
取書( ORDER BY book.id LIMIT 1
)。
UPDATE語句也可以是:
UPDATE Line
SET Line.id_book = (
SELECT MIN(book.id)
FROM book
WHERE book.id_user = Line.id_user
);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.