Obsługa typów danych

Inaczej niż większość baz danych SQL, mechanizm bazy danych SQL środowiska Adobe AIR nie wymaga ani nie egzekwuje przechowywania w kolumnach tabel wartości konkretnego typu. W środowisku wykonawczym stosowane są natomiast dwie koncepcje kontroli typów danych — klasy pamięci i powinowactwo kolumn. W niniejszej sekcji opisano koncepcję klasy pamięci i powinowactwa kolumn oraz sposoby rozstrzygania rozbieżności między typami danych obowiązujące w różnych sytuacjach

Klasy pamięci

Klasy pamięci reprezentują faktyczne typy danych wartości przechowywanych w bazie danych. Następujące klasy pamięci są używane przez bazy danych:

NULL
Wartość tej klasy jest wartością NULL.

INTEGER
Wartość jest liczbą całkowitą ze znakiem.

REAL
Wartość jest liczbą zmiennopozycyjną.

TEXT
Wartość jest ciągiem tekstowym (rozmiar ograniczony do 256 MB).

BLOB
Wartość jest dużym obiektem binarnym (BLOB); innymi słowy, są to „surowe” dane binarne (rozmiar ograniczony do 256 MB).

Przed wykonaniem instrukcji SQL wszystkim wartościom przekazywanym do bazy danych jako literały osadzone w instrukcji SQL lub wartościom powiązanym przez parametry z przygotowaną instrukcją SQL nadawana jest klasa pamięci.

Literały wchodzące w skład instrukcji SQL mają przypisaną klasę pamięci TEXT, jeśli są ujęte w apostrofy lub cudzysłowy, klasę INTEGER, jeśli są podane bez cudzysłowu jako liczby niezawierające kropki dziesiętnej lub znaku E, klasę REAL, jeśli są podane bez cudzysłowu jako liczby z kropką dziesiętną lub znakiem E, bądź klasę NULL, jeśli literał jest równy NULL. Literały klasy BLOB określa się, korzystając z zapisu X'ABCD'. Więcej informacji można znaleźć w sekcji Wartości literałowe.

Wartości podawane jako parametry przy użyciu tablicy asocjacyjnej SQLStatement.parameters otrzymują klasę pamięci możliwie najbardziej zbliżoną do natywnego typu parametrów. Na przykład wartości int otrzymują klasę pamięci INTEGER, wartości typu Number otrzymują klasę pamięci REAL, wartości typu String otrzymują klasę pamięci TEXT, w obiekty typu ByteArray otrzymują klasę pamięci BLOB.

Powinowactwo kolumn

Powinowactwo kolumny jest to zalecany typ danych przechowywanych w tej kolumnie. W momencie zapisywania wartości w kolumnie (za pomocą instrukcji INSERT lub UPDATE) środowisko wykonawcze próbuje przekonwertować tę wartość z jej typu danych na typ określony przez powinowactwo. Na przykład w momencie wstawiania wartości Date (instancji obiektu Date w języku ActionScript lub JavaScript) do kolumny, która ma powinowactwo do typu TEXT, wartość Date jest konwertowana na ciąg znaków typu String (co jest równoważne wywołaniu metody toString() obiektu), a dopiero potem zapisywana w bazie danych. Jeśli wartości nie da się przekonwertować na typ określony przez powinowactwo, występuje błąd i operacja nie jest wykonywana. Wartość pobierana z bazy danych za pomocą instrukcji SELECT jest zwracana jako instancja klasy odpowiadającej typowi określonemu przez powinowactwo, nawet jeśli podczas zapisywania w bazie danych została przekonwertowana z innego typu.

Jeśli kolumna dopuszcza wartości NULL, dozwolone jest podanie wartości null języka ActionScript lub JavaScript jako parametru w celu zapisania wartości NULL w kolumnie. Gdy instrukcja SELECT pobiera wartość klasy NULL, wartość ta jest zawsze zwracana jako wartość null w języku ActionScript lub JavaScript, niezależnie od powinowactwa kolumny. Jeśli kolumna dopuszcza wartości NULL, należy zawsze sprawdzać wartości pobierane z tej kolumny, aby ustalić, czy są równe null, zanim podejmie się próbę rzutowania ich na typ, który nie dopuszcza wartości null (np. Number lub Boolean).

Każda kolumna w bazie danych ma powinowactwo do jednego z następujących typów:

  • TEXT (lub String)

  • NUMERIC

  • INTEGER (lub int)

  • REAL (lub Number)

  • Boolean

  • Date

  • XML

  • XMLLIST

  • Object

  • NONE

TEXT (lub String)

Wszystkie dane w kolumnie z powinowactwem do typu TEXT lub String są zapisane w klasie pamięci NULL, TEXT lub BLOB. Dane liczbowe wstawiane do kolumny z powinowactwem do typu TEXT są uprzednio konwertowane do postaci tekstowej.

NUMERIC

Kolumna z powinowactwem do typu NUMERIC zawiera wartości należące do klas pamięci NULL, REAL i INTEGER. Przed wstawieniem danych tekstowych do kolumny typu NUMERIC podejmowana jest próba przekonwertowania tekstu na liczbę całkowitą lub rzeczywistą. Jeśli konwersja powiedzie się, wartość jest zapisywana w klasie pamięci INTEGER lub REAL (na przykład wartość '10.05' jest konwertowana na klasę pamięci REAL). Jeśli konwersja nie jest możliwa, występuje błąd. Nie są podejmowane próby konwertowania wartości NULL. Wartość pobierana z kolumny NUMERIC jest zwracana jako instancja najwęższego typu liczbowego, który może reprezentować tę wartość. Innymi słowy, jeśli wartość jest dodatnią liczbą całkowitą lub liczbą 0, jest zwracana jako instancja typu uint. Jeśli jest ujemną liczbą całkowitą, jest zwracana jako instancja typu int. Wreszcie, jeśli ma składnik zmiennopozycyjny (nie jest liczbą całkowitą), jest zwracana jako instancja typu Number.

INTEGER (lub int)

Kolumna z powinowactwem do typu INTEGER zachowuje się tak samo, jak kolumna z powinowactwem do typu NUMERIC — z jednym wyjątkiem. Jeśli zapisywana wartość jest liczbą rzeczywistą (np. instancją typu Number) bez składnika zmiennopozycyjnego lub jeśli jest wartością tekstową, którą da się przekonwertować na wartość rzeczywistą bez składnika zmiennopozycyjnego, to zostanie przekonwertowana na liczbę całkowitą i zapisana w klasie pamięci INTEGER. Próba zapisania wartości rzeczywistej ze składnikiem zmiennopozycyjnym powoduje wystąpienie błędu.

REAL (lub Number)

Kolumna z powinowactwem do typu REAL lub NUMBER zachowuje się jak kolumna z powinowactwem do typu NUMERIC, z tym że wymusza zmiennopozycyjną reprezentację wartości całkowitych. Wartość z kolumny typu REAL jest zawsze zwracana jako instancja klasy Number.

Boolean

Kolumna z powinowactwem do typu Boolean zawiera wartości true albo false. W kolumnie typu Boolean dopuszczalne są wartości będące instancjami klasy Boolean w języku ActionScript lub JavaScript. Jeśli kod próbuje zapisać wartość typu String, ciągi znaków o długości większej niż zero uznawane są za wartości true, a puste ciągi znaków za wartości false. Jeśli kod próbuje zapisać wartość liczbową, każda wartość niezerowa jest zapisywana jako wartość true, a 0 jest zapisywane jako wartość false. Wartości z kolumn typu Boolean pobierane za pomocą instrukcji SELECT są zwracane jako instancje klasy Boolean. Wartości różne od NULL są zapisywane w klasie pamięci INTEGER (0 oznacza false, a 1 oznacza true), a podczas pobierania są konwertowane na obiekty klasy Boolean.

Date

Kolumna z powinowactwem do typu Date zawiera wartości daty i godziny. W kolumnie Date dopuszczalne są wartości będące instancjami w języku ActionScript lub JavaScript. Próba zapisania wartości klasy String w kolumnie typu Date spowoduje, że środowisko wykonawcze podejmie próbę przekonwertowania tej wartości na datę wg kalendarza juliańskiego. Jeśli konwersja zakończy się niepowodzeniem, wystąpi błąd. Jeśli kod podejmie próbę zapisania wartości klasy Number, int lub uint, nie jest podejmowana próba sprawdzenia poprawności danych i przyjmuje się, że wartość jest poprawną datą wg kalendarza juliańskiego. Wartość typu Date pobierana za pomocą instrukcji SELECT jest automatycznie konwertowana na instancję obiektu Date. Wartości typu Date są przechowywane jako daty (numery dni) według kalendarza juliańskiego przy wykorzystaniu klasy pamięci REAL, a zatem operacje sortowania i porównania działają zgodnie z oczekiwaniami.

XML lub XMLList

Kolumna z powinowactwem do typu XML lub XMLList zawiera struktury XML. Gdy kod próbuje zapisać dane w kolumnie XML, korzystając z parametru SQLStatement, środowisko wykonawcze podejmuje próbę przekonwertowania i sprawdzenia poprawności wartości, używając do tego funkcji XML() lub XMLList() języka ActionScript. Jeśli wartości nie da się przekonwertować na poprawny kod XML, występuje błąd. Jeśli podejmowana jest próba zapisania literału tekstowego SQL (na przykład INSERT INTO (col1) VALUES ('Niepoprawny XML (brak znacznika zamykającego)'), wartość nie jest analizowana składniowo ani nie jest sprawdzana jej poprawność — przyjmuje się, że jest prawidłowo sformułowanym kodem XML. Jeśli zostanie zapisana niepoprawna wartość, to przy odczycie zostanie zwrócona jako pusty obiekt XML. Dane typu XML i XMLList są zapisywane w klasie pamięci TEXT lub klasie pamięci NULL.

Obiekt

Kolumna z powinowactwem do typu Object zawiera obiekty złożone języka ActionScript lub JavaScript, w tym instancje klasy Object oraz instancje podklas klasy Object, takie jak instancje Array, a nawet instancje klas niestandardowych. Dane z kolumn typu Object są serializowane w formacie AMF3 i przechowywane w klasie pamięci BLOB. Pobrana wartość jest deserializowana z formatu AMF3 i zwracana jako instancja klasy, która została pierwotnie zapisana. Należy zwrócić uwagę, że niektóre klasy języka ActionScript, w szczególności obiekty wyświetlane, nie mogą być deserializowane jako instancje oryginalnego typu danych. Przed zapisaniem instancji klasy niestandardowej należy zarejestrować alias klasy, korzystając z metody flash.net.registerClassAlias() (lub w module Flex, dodając metadane [RemoteObject] do deklaracji klasy). Ponadto przed pobraniem danych należy zarejestrować ten sam alias dla klasy. Wszelkie dane, których nie da się prawidłowo zdeserializować, albo z uwagi na charakterystykę samej klasy, albo z powodu braku lub niezgodności aliasu klasy, są zwracane jako obiekty anonimowe (instancje klasy Object) z właściwościami i wartościami odpowiadającymi pierwotnie zapisanej instancji.

NONE

Kolumny z powinowactwem NONE nie mają przypisanych preferencji co do klas pamięci. Nie są podejmowane próby konwersji danych wstawianych do takich kolumn.

Określanie powinowactwa

Powinowactwo kolumny do typu jest określone przez typ kolumny zadeklarowany w instrukcji CREATE TABLE. Przy określaniu typu obowiązują następujące reguły (bez uwzględniania wielkości liter):

  • Jeśli nazwa typu danych zawiera którykolwiek z ciągów „CHAR”, „CLOB”, „STRI” lub „TEXT”, wówczas kolumna ma powinowactwo do typu TEXT/String. Należy zwrócić uwagę, że nazwa typu VARCHAR zawiera ciąg znaków „CHAR”, dlatego powoduje przypisanie powinowactwa TEXT.

  • Jeśli nazwa typu danych kolumny zawiera ciąg znaków „BLOB” lub jeśli nie jest określony typ danych, wówczas kolumna ma powinowactwo NONE.

  • Jeśli nazwa typu danych kolumny zawiera ciąg znaków „XMLL”, wówczas kolumna ma powinowactwo do typu XMLList

  • Jeśli nazwą typu danych kolumny jest ciąg znaków „XML”, wówczas kolumna ma powinowactwo do typu XML.

  • Jeśli nazwa typu danych kolumny zawiera ciąg znaków „OBJE”, wówczas kolumna ma powinowactwo do typu Object.

  • Jeśli nazwa typu danych kolumny zawiera ciąg znaków „BOOL”, wówczas kolumna ma powinowactwo do typu Boolean.

  • Jeśli nazwa typu danych kolumny zawiera ciąg znaków „DATE”, wówczas kolumna ma powinowactwo do typu Date.

  • Jeśli nazwa typu danych kolumny zawiera ciąg znaków „INT” (w szczególności także „UINT”), wówczas kolumna ma powinowactwo do typu INTEGER/int.

  • Jeśli nazwa typu danych zawiera którykolwiek z ciągów „REAL”, „NUMB”, „FLOA” lub „DOUB”, wówczas kolumna ma powinowactwo do typu REAL/Number.

  • W przeciwnym razie kolumna ma powinowactwo do typu NUMERIC.

  • Jeśli tabela zostanie utworzona za pomocą instrukcji CREATE TABLE t AS SELECT..., wówczas żadna z kolumn nie ma określonego typu danych i wszystkie mają powinowactwo NONE.

Typy danych a operatory porównania

Obsługiwane są dwuargumentowe operatory porównania =, <, <=, >= oraz ! = oraz operacja testowania przynależności do zbioru, IN, jak również trójargumentowy operator porównania BETWEEN. Szczegółowe informacje o tych operatorach zawiera sekcja Operatory.

Wynik porównania zależy od klas pamięci porównywanych wartości. Przy porównywaniu dwóch wartości obowiązują następujące reguły:

  • Wartość z klasą pamięci NULL jest zawsze uznawana za mniejszą od każdej innej wartości (również od innej wartości z klasą pamięci NULL).

  • Wartość klasy INTEGER lub REAL jest mniejsza od każdej wartości klasy TEXT lub BLOB. Przy porównywaniu wartości klasy INTEGER lub REAL z innymi wartościami klasy INTEGER lub REAL wykonywane jest porównanie liczbowe.

  • Wartość klasy TEXT jest mniejsza od wartości klasy BLOB. Przy porównywaniu dwóch wartości klasy TEXT wykonywane jest porównanie binarne.

  • Przy porównywaniu dwóch wartości klasy BLOB wynik zawsze jest określany na podstawie porównania binarnego.

Operator trójargumentowy BETWEEN jest zawsze rzutowany jako równoważne wyrażenie dwuargumentowe. Na przykład wyrażenie a BETWEEN b AND c jest rzutowane na wyrażenie a >= b AND a <= c, nawet jeśli oznacza to zastosowanie różnych powinowactw do wartości a w każdym z porównań niezbędnych do obliczenia wartości wyrażenia.

Wyrażenia typu IN (SELECT b ....) są przetwarzane zgodnie z trzema wymienionymi wcześniej regułami dla porównań dwuargumentowych, tj. podobnie jak wyrażenia a = b. Na przykład jeśli b jest wartością kolumny, a a jest wyrażeniem, wówczas przed porównaniem powinowactwo b jest stosowane do a. Wyrażenie a IN (x, y, z) jest rzutowane na wyrażenie a = +x OR a = +y OR a = +z. Wartości po prawej stronie operatora IN (w tym przykładzie są to wartości x, y i z) są uznawane za wyrażenia, nawet jeśli są wartościami kolumn. Jeśli wartość po lewej stronie operatora IN jest kolumną, wówczas przyjmowane jest powinowactwo tej kolumny. Jeśli wartość jest wyrażeniem, nie jest wykonywana żadna konwersja.

Na sposób wykonywania porównań może mieć również wpływ użycie klauzuli COLLATE. Aby uzyskać więcej informacji, należy zapoznać się z opisem instrukcji COLLATE.

Typy danych a operatory matematyczne

Dla każdego z obsługiwanych operatorów matematycznych, *, /, %, + i -, przed obliczeniem wartości wyrażenia stosowane jest powinowactwo do typu liczbowego. Jeśli któregokolwiek operandu nie można pomyślnie przekonwertować na klasę pamięci NUMERIC, wynikiem wyrażenia będzie NULL.

W przypadku użycia operatora konkatenacji || wszystkie operandy są przed obliczeniem wartości wyrażenia konwertowane na klasę pamięci TEXT. Jeśli któregokolwiek operandu nie można pomyślnie przekonwertować na klasę pamięci TEXT, wynikiem wyrażenia będzie NULL. Brak możliwości przekonwertowania wartości może wynikać z dwóch przyczyn: operand ma wartość NULL lub operand jest obiektem BLOB zawierającym obiekt klasy pamięci innej niż TEXT.

Typy danych a sortowanie

Przy sortowaniu wartości za pomocą klauzuli ORDER BY wartości klasy pamięci NULL mają pierwszeństwo. Po nich następują wartości klasy INTEGER i REAL w kolejności liczbowej (bez pierwszeństwa dla którejkolwiek z tych dwóch klas), a po nich wartości klasy TEXT w kolejności binarnej lub w oparciu o określony sposób porównywania (BINARY lub NOCASE). Na koniec trafiają wartości BLOB w kolejności binarnej. Przed sortowaniem klasy pamięci nie są konwertowane.

Typy danych i grupowanie

Przy grupowaniu wartości za pomocą klauzuli GROUP BY wartości należące do różnych klas pamięci są uznawane za różne. Wyjątkiem są wartości klasy INTEGER i REAL, które uznaje się za równe, jeśli są równe liczbowo. W wyniku działania klauzuli GROUP BY nie są stosowane żadne powinowactwa.

Typy danych a złożone instrukcje SELECT

Złożone operatory instrukcji SELECT — UNION, INTERSECT i EXCEPT — dokonują niejawnych porównań między wartościami. Przed dokonaniem porównania możliwe jest zastosowanie powinowactwa do wartości. To samo powinowactwo jest stosowane do wszystkich wartości potencjalnie zwracanych w jednej kolumnie zbioru wynikowego złożonej instrukcji SELECT. Stosowane jest powinowactwo kolumny zwróconej przez pierwszy element złożonej instrukcji SELECT będący wartością kolumny (a nie innym rodzajem wyrażenia). Jeśli dla danej kolumny złożonej instrukcji SELECT żadna ze składowych instrukcji SELECT nie zwraca wartości kolumny, do wartości tej kolumny przed porównaniem nie są stosowane żadne powinowactwa.