W jaki sposób obsługiwane są klucze auto_increment w INSERT (WYBIERZ * Z…)


13

Mam table1i table2w MySQL. Oba mają auto_incrementklucz podstawowy id.

Jeśli schematy tabel są zgodne, a ja robię, INSERT INTO table1 (SELECT * FROM table2)co się stanie w odniesieniu do nowych wierszy wstawionych do table1? Czy zachowują swoje stare idwartości i generują konflikty, gdy wiersz table1ma to samo id? Czy nowe wartości są generowane przez auto_increment? Czy to zależy od silnika pamięci lub blokady?

Odpowiedzi:


13

Możesz wstawić do kolumny automatycznego przyrostu i podać wartość. Jest okej; po prostu zastępuje generator auto-przyrostowy.

Próba wprowadzenia wartości NULL lub 0 lub DEFAULTpominięcie kolumny automatycznego przyrostu w kolumnach instrukcji INSERT powoduje uaktywnienie generatora automatycznego przyrostu.

Więc dobrze jest INSERT INTO table1 SELECT * FROM table2(nawiasem mówiąc, nie potrzebujesz nawiasów). Oznacza to, że wartości id table2zostaną skopiowane dosłownie i nietable1 będą generować nowych wartości.

Jeśli chcesz table1 wygenerować nowe wartości, nie możesz tego zrobić SELECT *. Możesz użyć null lub 0 dla kolumny id:

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

Albo pominiesz kolumnę z listy kolumn instrukcji INSERT i listy wyboru instrukcji SELECT:

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

Zanim zapytasz, w SQL nie ma składni dla „select * oprócz jednej kolumny”. Musisz przeliterować pełną listę nazw kolumn, które chcesz wstawić.


Czy nie ma opcji, która pozwala / nie zezwala na wstawienie 0 jako wartości? (W odniesieniu do drugiego akapitu)
— Sascha Rambeaud

1
Tak, SQL_MODE = NO_AUTO_VALUE_ON_ZERO , w przeciwnym razie nigdy nie moglibyśmy wstawić dosłownej wartości zerowej do kolumny AI. Jeśli używasz tego trybu SQL, NULL nadal działa, aby aktywować generator AI lub pominięcie kolumny również działa.
— Bill Karwin,

@BillKarwin, Jeśli chodzi o twój ostatni akapit, po uzyskaniu wyniku select * from table, czy nie ma sposobu na operację na tym wyniku, aby usunąć jego pierwszą kolumnę?
— Pacerier

@Pacerier, jeśli dobrze rozumiem, pytasz, czy select *może to oznaczać select * except for the first column. Odpowiedź brzmi nie. select *zawsze żąda wszystkich kolumn z tej tabeli. Jeśli chcesz mieć podzbiór, musisz przeliterować kolumny, które chcesz.
— Bill Karwin

@ BillKarwin, Hmm, myślałem o obróceniu stołu, aby zrobić pionowe klauzule, a następnie o odwróceniu go np. A select*from transpose(select*from(transpose(select*from table where Id=1))where col_name<>Id)może bardziej zwięźle select*from table where Id=1 and $col<>Id, jak myślisz?
— Pacerier

3

Identyfikator z zaznaczenia będzie tą samą wartością wstawioną do tabeli. Spowoduje to błąd, jeśli próbujesz powielić istniejące wiersze.

Bill Karwin: Zanim zapytasz, w SQL nie ma składni dla „select * oprócz jednej kolumny”.

Można to osiągnąć dzięki pewnej kreatywności:

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;

Spowoduje to, że nowy wiersz otrzyma automatycznie przyrostowy identyfikator zamiast identyfikatora z wybranego wiersza.


2
Sprytne, ale dla mnie liczy się to jako przeliterowanie pełnej listy nazw kolumn, które chcesz wstawić.
— Bill Karwin

1
Cóż, mysql automatycznie pisze to w porównaniu do robienia tego ręcznie. Jeśli masz tabele z dużą liczbą kolumn, zapobiegnie to pominięciu jednej lub błędnej pisowni kilku.
— curmil
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.