Pisanje in konflikti pri pisanju
Pisanje je enako dinamično kot branje: metoda, tabela, ključ in polja pridejo iz zahteve, stavek SQL
pa sestavi prehod. Vsaka tako sestavljena sprememba zadene natanko en zapis. Spremembo, ki jo je po
vašem branju naredil nekdo drug, prehod prepozna in je ne prepiše, če odjemalec v glavi
If-Match pošlje prebrano različico zapisa. Brez nje ali z If-Match: * obvelja zadnja sprememba.
Če to omogoči skrbnik, enako velja tudi za tabele brez različice vrstice in za tabele brez ključa.
Stavki, ki jih klicatelj napiše sam (preverjeni stavki in prepustna pot), lahko tako kot v SQL Serverju
spremenijo več zapisov hkrati; zanje ta stran ne velja.
Ključne funkcije
- En zapis, naslovljen s celotnim enoličnim ključem, nikoli s prostim pogojem.
- Optimistično zaklepanje z različico vrstice (
If-Match; v Accessu običajno sporočilo o konfliktu pri pisanju). - Izračunani žig vrstice za tabele, ki nimajo različice vrstice.
- Spreminjanje in brisanje po prvotnih vrednostih za tabele brez ključa.
Osnovni pojmi
En zapis, en ključ
Zapis je naslovljen s celotnim enoličnim ključem in z ničimer drugim. Ključ je primarni ključ
tabele, če ga ni, pa njen prvi enolični indeks. Če del ključa manjka ali zahteva poleg ključa vsebuje
še kakšen argument ali $filter, je zavrnjena. Delni ključ ali prost pogoj bi namreč zahtevi, v
kateri manjka ena vrednost, omogočil spremeniti ali izbrisati vse vrstice, ki ustrezajo preostanku.
Sestavljeni stavek je zavarovan še dodatno: izvede se v transakciji, prešteje zadete vrstice in spremembo razveljavi, če to ni natanko ena. Razveljavi jo do svoje točke shranjevanja, tako da v transakciji odjemalca razveljavi samo sebe.
Optimistično zaklepanje
Optimistično zaklepanje z If-Match. Če ima tabela različico vrstice ali je zanjo omogočen
žig vrstice, lahko pisanje vežete na prebrano vrednost.
Prehod jo sprejme v obliki, kot jo vrne branje (Base64), ali v zapisu SQL Serverja (0x…). Če se je
zapis medtem spremenil, prehod odgovori z 412 in ne zapiše ničesar. Brez If-Match obvelja
sprememba tistega, ki je pisal zadnji, in sicer pri poljih, ki jih je navedel.
Tabele brez različice vrstice: žig vrstice
Sprememba, ki ne sme prepisati tuje spremembe, potrebuje vrednost, ki se spremeni ob vsaki spremembi
zapisa. Tabela z različico vrstice jo ima. Pri tabeli brez nje lahko odjemalec v pogoj zapiše le
prvotne vrednosti vseh stolpcev (tako ravna Access pri neposredni povezavi). Tega pa ne more prenesti
noben od obeh vmesnikov, ker If-Match vsebuje eno oznako, ne seznama vrednosti.
Za take tabele prehod na zahtevo izračuna žig vrstice: zgoščeno vrednost SHA-256 prek vseh
shranjenih stolpcev zapisa, ki jo izračuna kar podatkovna zbirka. Žig je viden enako kot različica
vrstice: kot stolpec samo za branje gw_rowstamp (binary(32)), kot @odata.etag in glava ETag ter
z napovedjo Core.OptimisticConcurrency v dokumentu metapodatkov. Pri spreminjanju in brisanju se na
novo izračuna in primerja v istem stavku, ki piše, zato med preverjanjem in pisanjem ne more
nihče drug spremeniti zapisa. Odjemalec, ki zna delati z različicami vrstic, ne potrebuje ničesar
dodatnega, podatkovna zbirka pa nobenega novega stolpca.
Kako se žig izračuna. Vsak stolpec prispeva svoje shranjene bajte, pred katerimi je navedena
njihova dolžina; manjkajoča vrednost prispeva en sam bajt 0xFF. Dolžina zagotovi, da je zapis
enoznačen (brez nje bi ('ab', 'c') in ('a', 'bc') dala iste bajte), posebna oznaka pa loči
“manjka” od “prazno”. Uporabljeni so bajti, ne besedilo, ker je besedilna oblika odvisna od stvari, ki
niso del vrednosti: pri datumu od jezika seje, pri money in float od zaokroževanja. Pri ponovnem
branju je žig enak, vsaka sprememba shranjene vrednosti pa ga spremeni. To velja tudi za četrto
decimalko vrednosti money, najmanjšo spremembo vrednosti float, 100 ns pri datetime2, spremembo
samo velikih in malih črk, iste bajte v drugem tipu pri sql_variant, geography, hierarchyid,
json in vector, stolpec s presledkom v imenu ter NULL v primerjavi s praznim besedilom.
Stolpcev text, ntext, json in vector ni mogoče neposredno pretvoriti v bajte, zato se pretvorijo
prek varchar(max) oziroma nvarchar(max).
Omejitve žiga in zakaj ni privzeto vklopljen povsod:
- Vrednost, ki se spremeni in nato vrne na prejšnjo, spet da isti žig. Žig opisuje stanje, sprememb ne šteje; različica vrstice, ki jo vzdržuje SQL Server, te vrzeli nima.
- Pri vsakem branju se izračuna za vsako vrnjeno vrstico prek vseh stolpcev, tudi velikih besedilnih. Pri širokih tabelah to vsako branje upočasni.
- Primerja bajte in ne besedila po pravilih razvrščanja. Sprememba samo velikih in malih črk zato šteje kot sprememba, čeprav SQL Server pri primerjavi obe vrednosti šteje za enaki. Žig je torej strožji, nikoli ohlapnejši.
Kjer smete spreminjati shemo, je stolpec z različico vrstice še vedno boljša rešitev: je natančen, vzdržuje ga SQL Server in pri branju ne pomeni nobenega dodatnega dela.
Žig je na voljo tudi za tabelo brez ključa, ki je
navedena v KeylessWriteTables. Tam je del naslova in pokrije tudi dolga besedila, ki jih primerjava
posameznih vrednosti ne zajame.
Tabele brez ključa
Tabela brez enoličnega ključa nima naslova za “ta zapis”, zato je brez posebne sprostitve samo za branje. Aplikacija, ki tako tabelo ureja prek neposredne povezave, zapis določi po njegovih prvotnih vrednostih. Tako piše Access prek neposredne povezave, potem ko je bil ob povezovanju izbran nadomestni ključ:
UPDATE "t" SET "Text"=? WHERE "Nummer" = ? AND "Text" = ? AND "Betrag" IS NULL AND "Wert" IS NULL AND "Datum" IS NULL AND "Aktiv" = ?
Access pri tem navede vsak stolpec razen dolgega besedila (nvarchar(max)) in za manjkajočo prvotno
vrednost sam zapiše IS NULL. Natanko to obliko prehod sprejme za tabele, ki so pri aliasu sproščene
v KeylessWriteTables:
- Prvotne vrednosti morajo zapis opisati v celoti: z vsakim primerljivim stolpcem ali z različico oziroma žigom vrstice. Z manj stolpci bi pogoj zadel tudi zapise, ki se razlikujejo samo v drugih stolpcih.
- Manjkajoča prvotna vrednost postane
IS NULL. - Spremeni ali izbriše se natanko en zapis. Če prvotne vrednosti zadenejo več zapisov (ki so enaki v vseh primerljivih stolpcih), prehod spremembo razveljavi in odgovori z
409. Enako ravna Access pri neposredni povezavi: sporoči napako 3362 in spremembo prav tako razveljavi. - Če pogoj ne zadene nobenega zapisa, prehod odgovori z
412: zapis je bil medtem spremenjen ali izbrisan, brez ključa pa obeh primerov ni mogoče razlikovati.
Dejanja vmesnika OData in njihovi odgovori so opisani v razdelku Tabele brez ključa: dejanja.