Wpis z mikrobloga

W sumie podpada to pod 3 tagi, więc sorry za spam, ale:

Jeśli w MySQL użyję: UPDATE tabela SET starenetto=netto, netto = 100, brutto = netto * 1,23;

to czy brutto mi się ustawi poprawnie na 123zł, a poprzednie netto zostanie zapamiętane?

W sensie, czy przypisania pól są GWARANTOWANE do wykonywania się od lewej do prawej i te wartości można wykorzystać dalej w jednym zapytaniu, czy wszystkie pola są wczytywane do pamięci i ich wartości są brane do wyliczeń (wtedy pośrednie zmiany byłby ignorowane).

W dokumentacji pisze tylko, że pola "Z REGUŁY ewaluowane / updatowane są od lewej do prawej". Martwi mnie to "z reguły".. ;)

#programowanie #mysql #bazydanych
  • 13
Trzeba rozbić, na dwa zapytania.

UPDATE tabela SET starenetto=netto

UPDATE tabela SET netto = xxx, brutto = xxx*tax;

UPDATE t1 SET col1 = col1 + 1, col2 = col1;

Single-table UPDATE assignments are generally evaluated from left to right. For multiple-table updates, there is no guarantee that assignments are carried out in any particular order.
@aaadaaam: No właśnie mam - że tak powiem - "dwa" zapytania. Jestem jakby na etapie optymalizacji triggerów i w sumie odbiłem się od problemu, który sprowadza się do jak powyżej. Po prostu zaciekawiło mnie na ile mogę to połączyć. Mam single table, więc tu jest okej. Mam dane krytyczne, więc "are generally" nie jest okej.

Po prostu chciałbym puścić jeden update do wiersza, zamiast kilku sekwencyjnie jeden po drugim. Ale się
@aaadaaam: to zapytanie powyżej jest proste, bo tak je przedstawiłem, żeby zademonstrować problem i o co mi chodzi :)

Indeksy są, kardynalność( ?) indeksów też dobra, ale wierszy po kluczu może być w cholerę. Po prostu w trakcie pracy zafascynował mnie sam fakt, że ktoś kiedyś się bał to połączyć i czy może jednak nie da się tego zrobić inaczej :)
@RRybak: może lepiej zrobić drugą tabelę tylko z netto i brutto oraz ustawić relacje do tej z produktem, czy co tam jest, wtedy będziesz mógł łatwiej updatować i miał historię cen
Inna sprawa to sama struktura. :) Dobrze gada @m21d24:

netto i starenetto sugerowałby, że masz tylko cenę oraz poprzednią ceną bez pełnej historii zmian.

lepiej byłoby zrobić

[produkt]

id serial Not NULL

nazwa varchar [50]

[cena]

id serial Not NULL

id-produkt integer/longint (klucz obcy) Not NULL

id-stawkavat integer/longint (klucz obcy) Not NULL

cena-netto number(10,2)

cena-brutto number(10,2)

czy-aktualna default true (niekoniecznie)

data-zmiany datetime/date (on insert now())

"-" zastapić dolną kreską.
@m21d24: @aaadaaam: ej ej ej.. spokojnie ;) Zmiana struktur na tym etapie nie wchodzi już raczej w grę - system jest zbyt rozbudowany :P (tak, jest parę/naście/dziesiąt) milionów wierszy ;)

Generalnie ja se z tym dam radę - po prostu zastanowił mnie ten konkretny fakt, jak MySQL sobie radzi z takimi zapytaniami i jak je ugryźć, żeby się nie zadławić :)

Póki co, mogę zostawić w tym miejscu dwa zapytania,
@m21d24:

kolumna czy-aktualna nie jest konieczna (denormalizacja) aczkolwiek może w pewnych warunkach przyśpieszyć działanie.

Do wyciągania ceny możesz stworzyć obiekt produkt->left join [cena] on cena.id_produkt = produkt.id where czy-aktualna = 't' / 1
Póki co, mogę zostawić w tym miejscu dwa zapytania, ale ciekawość i tak mnie zżera :P


@RRybak: Zrób kopie, odpal i pochwal się wynikami. znając życie może działać, aż do jakiejś zmiany konfiguracji BD/ migracji do nowszej wersji serwera.
@aaadaaam: generalnie to działa. Na 5.0 i 5.5. Schematy testowe jak wyżej "ustaw netto, wykorzystaj kolumnę do brutto" niby chodzą. "Generalnie" i "niby". Jako jednak, że w dokumentacji jest o magiczne "z reguły", a jest to system finansowy, to chyba nie odważę się puścić tego na większą skalę :)
@RRybak: Będzie dzialało do czasu....

a jest to system finansowy


Ja bym forsował refaktoryzacji aplikacji.

To się robi. Systemy się zmieniają coś co miało być na rok, służy potem wiele lat i pojawia się problem jak tutaj z ceną.