Các khóa auto_increment được xử lý như thế nào trong CHERTN (CHỌN * TỪ)


12

Tôi có table1table2trong MySQL. Cả hai đều có auto_incrementkhóa chính id.

Nếu các lược đồ bảng khớp và tôi làm INSERT INTO table1 (SELECT * FROM table2)gì xảy ra liên quan đến các hàng mới được chèn vào table1? Họ có giữ các idgiá trị cũ của mình và tạo ra xung đột khi một hàng từ table1có cùng idkhông? Là các giá trị mới được tạo bởi auto_increment? Nó phụ thuộc vào công cụ lưu trữ hoặc khóa?

Câu trả lời:


13

Bạn có thể chèn vào cột tăng tự động và chỉ định giá trị. Điều này là tốt; nó chỉ đơn giản ghi đè trình tạo tăng tự động.

Nếu bạn cố gắng chèn giá trị NULL hoặc 0 hoặc DEFAULTnếu bạn bỏ qua cột tăng tự động khỏi các cột trong câu lệnh INSERT, điều này sẽ kích hoạt trình tạo tăng tự động.

Vì vậy, thật tốt INSERT INTO table1 SELECT * FROM table2(nhân tiện, bạn không cần dấu ngoặc đơn). Điều này có nghĩa là các giá trị id trong table2sẽ được sao chép nguyên văn và table1sẽ không tạo ra các giá trị mới.

Nếu bạn muốn table1 tạo ra các giá trị mới, bạn không thể làm được SELECT *. Bạn sử dụng null hoặc 0 cho cột id:

INSERT INTO table1 SELECT 0, col1, col2, col3, ... FROM table2;

Hoặc nếu không, bạn bỏ qua cột từ cả danh sách cột của câu lệnh INSERT và danh sách chọn của câu lệnh SELECT:

-- No id in either case:
INSERT INTO table1 (col1, col2, col3) SELECT col1, col2, col3, ... FROM table2;

Trước khi bạn hỏi, không có cú pháp nào trong SQL cho "select * ngoại trừ một cột". Bạn phải đánh vần danh sách đầy đủ các tên cột bạn muốn chèn.


Không có tùy chọn nào cho phép / không cho phép chèn 0 làm giá trị? (Về đoạn 2 của bạn)
Sascha Rambeaud

1
Có, SQL_MODE = NO_AUTO_VALUE_ON_ZERO , nếu không, chúng tôi không bao giờ có thể chèn giá trị bằng 0 vào cột AI. Nếu bạn sử dụng chế độ SQL này, NULL vẫn hoạt động để kích hoạt trình tạo AI hoặc bỏ qua cột cũng hoạt động.
Bill Karwin

@BillKarwin, Liên quan đến đoạn cuối cùng của bạn, sau khi nhận được subresult select * from table, không có cách nào để hoạt động trên subresult này để loại bỏ cột đầu tiên của nó?
Pacerier

@Pacerier, nếu tôi hiểu chính xác, bạn đang hỏi nếu select *có thể có nghĩa select * except for the first column. Câu trả lời là không. select *luôn yêu cầu tất cả các cột từ bảng đó. Nếu bạn muốn một tập hợp con, bạn phải đánh vần các cột bạn muốn.
Bill Karwin

@BillKarwin, Hmm, tôi đã nghĩ đến việc xoay vòng bảng để thực hiện các mệnh đề thẳng đứng, sau đó xoay nó trở lại, ví dụ như select*from transpose(select*from(transpose(select*from table where Id=1))where col_name<>Id)hoặc có lẽ ngắn gọn hơn select*from table where Id=1 and $col<>Id, bạn nghĩ gì?
Pacerier

3

Id từ lựa chọn sẽ có cùng giá trị được chèn vào bảng. Điều này sẽ dẫn đến lỗi nếu bạn đang cố gắng sao chép các hàng hiện có.

Bill Karwin: Trước khi bạn hỏi, không có cú pháp nào trong SQL cho "select * ngoại trừ một cột".

Điều này có thể đạt được với một số sáng tạo:

SET @sql = CONCAT('INSERT INTO <table> SELECT null, 
    ', (SELECT GROUP_CONCAT(COLUMN_NAME) 
    FROM information_schema.columns 
    WHERE table_schema = '<database>' 
    AND table_name = '<table>' 
    AND column_name NOT IN ('id')), ' 
from <table> WHERE id = <id>');  

PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

Điều này sẽ dẫn đến hàng mới nhận được id tăng tự động thay vì id từ hàng đã chọn.


2
Thông minh, nhưng với tôi, điều đó được tính là đánh vần danh sách đầy đủ các tên cột bạn muốn chèn.
Bill Karwin

1
Vâng, mysql tự động đánh vần nó so với làm thủ công. Nếu bạn có các bảng có nhiều cột, nó sẽ ngăn bạn bỏ lỡ một hoặc sai chính tả.
curmil
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.