Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: skladnia INSERT ... SELECT
Forum PHP.pl > Forum > Bazy danych > MySQL
Aven
witam,

podczas pisania pewnego projektu natknalem sie oczywiscie na cos czego nie potrafie zrobic w "ładny sposób".

chce przerzucic z jednej tabeli do drugiej pewne wartosci z pól. Nie sa to wszystkie wartosci, tylko okreslone (i nie sa w tej samej kolejnosci).

w manualu MySQL jest skladnia INSERT SELECT, ktora w zasadzie powinna rozwiazac moj problem, ale widac zle jej uzywam :-(

mam cos takiego :

Kod
$zapytanie="INSERT INTO tabela2 VALUES ('id','partner','id','email','nazwa','link','katalog') SELECT FROM tabela1 WHERE partner='$ident";

tabele maja rozna ilosc pol.

wartosc pierwsza id to autoinkrementacja, a druga id to wartosc którą chcialbym pobrac z tabeli1. (wiem ze to co napisalem jest zle tongue.gif )

Mozna to oczywiscie zrobic w petli dwoma zapytaniami, ale czasami warto sobie utrudnic :-)

Prosze wszystkich "wiedzacych" jak zadac takie zapytanie o pomoc.
uboottd
[sql:1:187cfbcd69]
INSERT INTO tabela2
(id, partner, inny_id, email, nazwa, link, katalog)
SELECT NULL, partner, id, email, nazwa, link, katalog
FROM tabela1 WHERE
partner='$ident'
[/sql:1:187cfbcd69]

Uwagi:
- po nazwie tabeli wystepuja nazwy z tabeli do ktorej wsadzasz wiec istnienie tam dwa razy id jest bez sensu, zalozylem ze pole nazywa sie id a to drugie to inny_id - dostosuj sobie
- jesli pole jest autoincrement to mozesz albo je po prostu pominac w liscie pol, albo wsadzac tam wartosc NULL jak masz w przykladzie - wtedy zostanie wsadzona nastepna wartosc generowana
- ilosc pol po tabela2 i w SELECTcie musi byc taka sama i w tej samej kolejnosci - sa one w tej kolejnosci przypisywane
- dla mysql <4.0.14 nie mozna robic SELECT-a do bazy do ktorej INSERT-ujesz
Aven
dzieki za pomoc ...

pozmienialem, wyprobowalem i ... :-(

[sql:1:9298c11d4f]
INSERT INTO newsletter
VALUES (id, partner_id, link_id, email, nazwa, link, kategoria)
SELECT NULL, partner, id, email, nazwa, link, katalog
FROM tabela
WHERE partner='$identyfikator'
[/sql:1:9298c11d4f]

1064
You have an error in your SQL syntax near 'SELECT NULL, partner, id, email, nazwa, link, katalog FROM tabela WHERE partne' at line 3

1064 to jest PARSE ERROR :-(

liczba w values i select sie zgadza. probowalem bez nulla i id. probowalem bez nawiasow, z nawiasami eh :-(.
- nazwy w values i select sa takie jak faktyczne kolumny w tabelach.
- kolejnosc jest tez dobra

co tu jest nie tak ? :-)

pozdrawiam
uboottd
[sql:1:331131b8dc]
INSERT INTO newsletter (id, partner_id, link_id, email, nazwa, link, kategoria)
SELECT NULL, partner, id, email, nazwa, link, katalog
FROM tabela WHERE partner='$identyfikator'
[/sql:1:331131b8dc]

Skad wytrzasnales to VALUES u siebie ? angrysmiley.gif
Skladnia jest INSERT INTO ... SELECT ...
A nie INSERT INTO ... VALUES ... SELECT ...
Aven
faktycznie nie wiem skad to wzialem :-)
teraz dziala bez zarzutów
dzieki wielkie !!!!! biggrin.gif
Aven
do glowy wpadl mi jeszcze jeden pomysl ...
czy da sie sformulowac to zapytanie do bazy tak zeby jednoczesnie sprawdzalo czy gdzies w tabeli docelowej nie ma juz wpisu ktory ma byc do niej dodany?
chodzi o to zeby do tabeli docelowej nie trafialy dwa razy te same rekordy.

czy w mysql jest wogole taka skladnia ktora na to pozwala ?

jesli nie ma to niestety bede musial i tak robic wszystko jeszcze raz kilkoma zapytaniami w php :-(

pozdrawiam
Jabol
indexy unique?
uboottd
Jabol: nie chodzi o wywalenie zapytania, ale o wstawienie tylko potrzebnych indeksow.

Da sie, ale po pierwse mysql 4.0.14 dopiero to wspiera i jest to ze wzgledu na brak podzapytan dosc trudne i zagrzybione. Mam to poskladac ?
Aven
w zasadzie na serwie na ktorym sie to znajduje jest chyba nawet wyzsza wersja php.

mysle jednak ze jest to i tak nie na moja glowe, wiec sobie juz poradzilem inaczej :-)
Jabol
ubootd: kazdy sposob jest dobry

a wogole to mozna to zrobic tak:
wczesci select dac podselect (jak powiedzaj ubootd)[sql:1:79672ebea6]WHERE id not in ( select id from table );[/sql:1:79672ebea6]

//edit
ubottd:ahhh i znowy tylko przeglodam posty... pokarz jak bo sam jestem ciekawy
uboottd
A bos dawno mysqla nie mial i sie Ci w d... poprzewracalo ! aaevil.gif

[sql:1:8f678cebe9]
insert into tabela2 (pola...)
select pola...
from tabela1 left join tabela2 on tabela1_id = tabela2_id
where tabela2_id is null;
[/sql:1:8f678cebe9]

Aven: wersja mysql-a nie php-a. Nie ma w tej chwili oficjalnego mysql-a wyzszego od 4.0.14.
Jabol
uboottd: ale to musialbys dac outer joina?
uboottd
Mozna prosic calym zdaniem ?
Jabol
Aby osiagnoc zamierzony przez Ciebie efekt join wymaga byc outer joinem (a AFAIK defaultowy to inner join) wiec skladnia powinna byc.[sql:1:aa7b797628]INSERT INTO tabela2 (pola...)
SELECT pola...
FROM tabela1 LEFT OUTER join tabela2 ON (tabela1_id = tabela2_id)
WHERE tabela2_id IS NULL;[/sql:1:aa7b797628]Tak conajmniej mi sie wydaje.

przy inner joinach nie daje nulla przy łączeniu tylko po prostu nie łączy pól bez odpowieników.
uboottd
W zasadzie a i owszem, ale nie do konca. Widzisz jakas zasadnosc zapisu LEFT INNER JOIN ? Bo zapis ten jest zreszta nielegalny. Wiec slowko OUTER staje sie w tym momencie opcjonalnym dodatkiem - sklejenie i tak jest outer.

A, i lacza sie wiersze a nie pola winksmiley.jpg
Jabol
chyba rzeczywiscie dawno mysql nie mialem (za dawno ... ). Ale jak ktos kiedys mondrze powiedzial (nie o tym, ale to szczegół), "w jedną stronę trudno, w drugą niemożliwe".
uboottd
W obie strony mozna, trza tylko pamietac o zwyczajach.

postgres tez nie przyjmie Ci left inner join.
Jabol
ale "left join" oznacza "inner join" o ile wiem na mysqlu? a ogolnie to wlasciwie nie wiem... kurcze, bo w mysqlu left i right join to to samo, czyli są inner, ale w postgresie chyba rzeczywiście defaultowo jest outer w takich przypadkach i dla inner trzeba napisac inner albo lanczyc przez where.
uboottd
Dobra, to jasno i prosto:
Sklejenie mozebyc _albo_ INNER _albo_ jedno z LEFT, RIGHT, FULL ktore moga byc tylko i wylacznie OUTER. I podanie OUTER jest opcjonalne bo nic nie zmienia. Mozna inaczej powiedziec ze LEFT, RIGTH i FULL sa rodzajami sklejenia OUTER.

I dotyczy to wszystkich normalnych serwerow bazodanowych (a co namniej Oracla, MySQL-a i PostgreSQL-a) bo wynika to z teorii.

A, i powalilo ? na Mysqlu LEFT i RIGHT nie jest jednoznaczne. Oznacza dokladnie to co powinno..
Jabol
1 ostatnio mało sypiam ;P
2 ktos ostatnio na forum cytował manuala
3 zostawmy ten temat bo cos mi sie mieszac zaczyna
adwol
Cytat
ale "left join" oznacza "inner join" o ile wiem na mysqlu?

Nie, w mysqlu left join to left join czyli złączenie zewnętrzne lewe, a inner to inner czyli wewnętrzne.
Cytat
a ogolnie to wlasciwie nie wiem... kurcze, bo w mysqlu left i right join to to samo, czyli są inner

Chyba jednak nie. winksmiley.jpg
Cytat
ale w postgresie chyba rzeczywiście defaultowo jest outer w takich przypadkach i dla inner trzeba napisac inner albo lanczyc przez where.

Nie. Domyślnie w pg słowo kluczowe JOIN daje złączenie wewnętrzne. CROSS JOIN albo najpopularniejszy przecinek daje kartezjańskie (które po dodaniu warunku po WHERE staje się wewnętrznym), a zewnętrzne należy wymusić przez podanie LEFT, RIGHT lub FULL i opcjonalnie po nim OUTER.
Polecam poczytać o typach złączeń:
http://www.postgresql.org/docs/7.3/static/...expressions.html
uboottd
ad 1. Z tym Ci nie pomoge. winksmiley.jpg
ad 2. To nie wiem jak on cytowal:
"RIGHT JOIN works analogously as LEFT JOIN." - Analogicznie nie oznacza tak samo.
Jabol
jezeli chodzi o pg to ja to znam, po prostu miesza mi sie z tym mysql'em. brrr... dobrze, postanowienie. nie wypowiadam się więcej na tematy o mysql'u, bo kurka tylko ludzi w błąd wprowadzam.

ps.
no wlasnie, jedno slowko...
piratt
Witam wszystkich.

Mam male pytanko;) dotyczace INSERT.. SELECT'a.

INSERT `bgraczy` (idGracza,idBudynku,poziomBudynku) SELECT gracze.id,budynki.id,1 FROM gracze,budynki WHERE gracze.nick='gracz' and budynki.shortnazwa='Rada1';

Ta kwerenda dziala bardzo dobrze, jednak problem pojawia sie gdy obie dodawane wartosci maja pochodzic z tego samego pola z tej samej tabeli(roznia sie tylko rekordy). Napisalem takie cos:

INSERT `wymbud` (idBudynku,idBudynkuWym,pozBudynkuWym) SELECT budynki.id,cos.id,'1' FROM budynki as cos INNER JOIN budynki WHERE budynki.shortnazwa='Wojenny3' AND cos.shortnazwa='Wojenny2';

Czy da sie to napisac w jakis prostszy sposob?

Pozdrawiam
Michał
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.