簡體   English   中英

SQL:如何在不丟失現有元素關系的情況下從“指向tableB的tableA”更新為“指向指向tableB的tableC的引用”?

[英]SQL: How to update from 'tableA pointing to tableB' to 'tableA poiting to tableC pointing to tableB' without losing existing element relation?

基本上,我想要一Book介於LineUser之間的直接鏈接之間的中間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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM