2012-04-01 8 views
6

Czy ktoś może mi powiedzieć, co wynika z następujących powinny być zgodne z normą (odniesienie do odpowiedniej części normy byłoby mile widziane)Co mówi standard SQL o warunkach zależnych w AKTUALIZACJI?

> select * from t1; 
+------+ 
| col1 | 
+------+ 
| 9 | 
| 8 | 
| 10 | 
+------+ 
> update t1 
    set col1 = col1 * 2 
    where col1 <= (select avg(col1) from t1); 

Chodzi o to: Czy ostatni wiersz aktualizowane, ponieważ jeśli wiersze są aktualizowane w kolejności, a średnia jest ponownie obliczana dla każdego wiersza, to spełni warunek, czy też nie zostanie zaktualizowany, ponieważ jakiekolwiek dane zmienione przez tę instrukcję będą mogły być odczytane po uruchomieniu całej instrukcji?

EDYTOWANIE A co z tą sprawą?

> select * from t1; 
+------+------+ 
| col1 | col2 | 
+------+------+ 
| 9 | 1 | 
| 8 | 2 | 
| 10 | 2 | 
+------+------+ 
> update t1 p1 
    set col1 = col1 * 2 
    where col1 <= (select avg(col1) 
        from t1 
        where col2=p1.col2); 
+0

Tutaj najpierw wykonuje się podzapytanie. Więc średnia nie zmienia się. –

+0

@Shiplu Dziękuję. A co z drugim przypadkiem, w którym podzapytanie nie może być wykonane wcześniej? – baruch

+1

@baruch - Można go wstępnie wykonać, ponieważ oddzielna operacja odczytu identyfikuje wiersze do aktualizacji i przechowuje identyfikatory wierszy w szpulach lub podobnych, a aktualizacja jest wykonywana podczas odczytu z tej szpuli po zakończeniu odczytu. Taki jest plan, którego oczekiwałbym w SQL Server. Nie jestem pewien, czy mogę zadać sobie trud sprawdzenia standardu SQL, aby znaleźć odpowiednie bity. Kilka pokrewnych pojęć to "operacje na raz" i ochrona przed halloweenami. –

Odpowiedz

4

O ile mogę powiedzieć, standard (rozdział 14.11, SQL 2003 - Foundation) jest całkiem jasne, o tym:

Kolumnę skutecznie obliczane dla każdego rzędu T przed każdy rząd T jest aktualizowana

(Kopalnia nacisk)

Moje rozumienie tego zdania, że ​​dowolny stan (czy nie związane współpraca) jest oceniana zanim rząd jest aktualizowana.

+0

... i jeden popularny (jeśli nie jedyny DBMS), który NIE jest zgodny ze standardem - i podobny do zapytań przykładów może spowodować niestandardowe wyniki - jest MySQL. –

+0

@ypercube: dlaczego nie jestem zaskoczony? –

+1

Szczerze mówiąc, jest to jedna z najpoważniejszych, jeśli nie najpoważniejsza, odchyleń od standardów. Nawet proste 'UPDATE t SET id = id + 1' są wykonywane szeregowo, a nie jako ustawiona operacja, i spowoduje naruszenia PK. –

2

Ostatni wiersz nie zostanie zaktualizowany. ponieważ "wybierz avg (col1) z t1" jest pod-zapytaniem, i uruchomi się najpierw, a wynik zostanie zapisany w tabeli tymczasowej, a następnie wykona polecenie update.

+0

Dziękuję. Czy możesz obejrzeć moją edycję? – baruch

4

O pierwszej kwerendzie subquery wykonany pierwszy więc, nie ma żadnych zmian w średni ...

O drugie zapytanie, używasz aliasu w UPDATE oświadczeniem ale używasz aliasu w niewłaściwym podejściem.

Prawidłowe i standardowy sposób użyć aliasu w UPDATE jest stwierdzenie:

UPDATE p1 
    set col1 = col1 * 2 
from t1 p1 
    where col1 <= (select avg(col1) 
        from t1 
        where col2=p1.col2); 
+2

Standard SQL nie zezwala na klauzulę 'FROM' dla instrukcji' UPDATE'. Twój przykład nie jest "standardową drogą". Dodatkowo w standardzie SQL alias tabeli jest zdefiniowany w części 'UPDATE':' UPDATE [[AS] ] '. Powyższa składnia jest ważna tylko dla MySQL, jeśli się nie mylę –

+0

@ a_horse_with_no_name: Dziękuję .... Działa na serwerze MS-SQL .. Już testowałem powyższe zapytanie w MSSQL Ale kiedy wykonuję drugie zapytanie OP, to wyrzuca błąd ... –

+0

dzięki za aktualizację. –

Powiązane problemy