Mam prostą tabelę mysql:
CREATE TABLE IF NOT EXISTS `pers` (
`persID` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(35) NOT NULL,
`gehalt` int(11) NOT NULL,
`chefID` int(11) DEFAULT NULL,
PRIMARY KEY (`persID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `pers` (`persID`, `name`, `gehalt`, `chefID`) VALUES
(1, 'blb', 1000, 3),
(2, 'as', 1000, 3),
(3, 'chef', 1040, NULL);
Próbowałem uruchomić następującą aktualizację, ale pojawia się tylko błąd 1093:
UPDATE pers P
SET P.gehalt = P.gehalt * 1.05
WHERE (P.chefID IS NOT NULL
OR gehalt <
(SELECT (
SELECT MAX(gehalt * 1.05)
FROM pers MA
WHERE MA.chefID = MA.chefID)
AS _pers
))
Szukałem błędu i znalazłem na stronie mysql http://dev.mysql.com/doc/refman/5.1/en/subquery-restrictions.html , ale to mi nie pomaga.
Co mam zrobić, aby poprawić zapytanie SQL?
sql
mysql
mysql-error-1093
CSchulz
źródło
źródło
Odpowiedzi:
Problem polega na tym, że MySQL, z jakiegokolwiek bezsensownego powodu, nie pozwala ci pisać takich zapytań:
Oznacza to, że jeśli robisz
UPDATE
/INSERT
/DELETE
na stole, nie można odwołać się w tej tabeli zapytania wewnętrznej (ty może jednak odwołać się od tego zewnętrznego pola tabeli ...)Rozwiązaniem jest zastąpienie wystąpienia
myTable
zapytania podrzędnego(SELECT * FROM myTable)
takim, jak toTo najwyraźniej powoduje, że niezbędne pola są domyślnie kopiowane do tabeli tymczasowej, więc jest to dozwolone.
Znalazłem to rozwiązanie tutaj . Uwaga z tego artykułu:
źródło
T
i(SELECT * FROM T)
są całkowicie równoważne. Są tą samą relacją. Dlatego jest to arbitralne, bezmyślne ograniczenie. Mówiąc dokładniej, obejściem tego problemu jest zmuszenie MySQL do zrobienia czegoś, co wyraźnie można zrobić, ale z jakiegoś powodu nie może on przeanalizować w swojej prostszej formie.DELETE FROM t WHERE tableID NOT IN (SELECT viewID FROM t_view);
Polecam także biegaćOPTIMIZE TABLE t;
później, aby zmniejszyć rozmiar stołu.Możesz to zrobić w trzech krokach:
...
lub
źródło
CREATE TABLE
instrukcjami - mam nadzieję, że autor był tego świadomy. Czy to jednak jedyne rozwiązanie? Czy zapytanie może zostać przepisane z podzapytaniami lub złączeniami? A dlaczego (nie) to robić?UPDATE Pers P
czytaćUPDATE pers P
?CREATE TABLE AS SELECT
daje okropnej wydajności?W Mysql nie można aktualizować jednej tabeli, subquery tej samej tabeli.
Możesz podzielić zapytanie na dwie części lub zrobić
źródło
SELECT ... SET
? Nigdy o tym nie słyszałem.AS B
drugie odniesienie doTABLE_A
. odpowiedź w najbardziej uprzywilejowanym przykładzie można uprościć, używającAS T
potencjalnie nieefektywnegoFROM (SELECT * FROM myTable) AS something
, co na szczęście optymalizator zapytań zazwyczaj eliminuje, ale nie zawsze to robi.Utwórz tabelę tymczasową (tempP) z podzapytania
Wprowadziłem osobną nazwę (alias) i nadałem nową nazwę kolumnie „persID” dla tabeli tymczasowej
źródło
SELECT ( SELECT MAX(gehalt * 1.05)..
- pierwszySELECT
nie wybiera żadnej kolumny.To całkiem proste. Na przykład zamiast pisać:
powinieneś pisać
lub podobne.
źródło
Podejście opublikowane przez BlueRaja jest powolne. Zmodyfikowałem je, ponieważ używałem do usuwania duplikatów z tabeli. W przypadku, gdy pomaga każdemu z dużymi tabelami Original Query
Zajmuje to więcej czasu:
Szybsze rozwiązanie
źródło
Jako odniesienie możesz również użyć Zmiennych MySQL, aby zapisać wyniki tymczasowe, np .:
https://dev.mysql.com/doc/refman/5.7/en/user-variables.html
źródło
Jeśli próbujesz odczytać pole A z tabeli A i zapisać je w polu B w tej samej tabeli, gdy fieldc = fieldd możesz to rozważyć.
Powyższy kod kopiuje wartość z pola A do pola B, gdy pole-warunek spełnia warunek. działa to również w ADO (np. dostęp)
źródło: próbowałem siebie
źródło
MariaDB zniosła to, zaczynając od 10.3.x (zarówno dla, jak
DELETE
iUPDATE
):DBFiddle MariaDB 10.2 - Błąd
DBFiddle MariaDB 10.3 - Sukces
źródło
Inne obejścia obejmują użycie SELECT DISTINCT lub LIMIT w podzapytaniu, chociaż nie mają one tak jednoznacznego wpływu na materializację. to zadziałało dla mnie
jak wspomniano w MySql Doc
źródło