SQL:如何从指向tableB'的表中更新to&table; a table to poiting to tableC指向tableB'在不丢失现有元素关系的情况下?

时间:2016-09-04 13:04:37

标签: mysql sql database database-design

基本上我想要一个中间人Book,介于从LineUser的直接链接之间。 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元素指向User元素,我不能从头开始创建新表。所以我需要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"

1 个答案:

答案 0 :(得分:1)

创建表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相关联。在您的问题中,您没有定义如何处理此案例。所以我决定在idORDER 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
);