# Store

Instrukcja Store tworzy plik QVD, Parquet, CSV lub TXT.

Składnia:

Store [ fieldlist from] table into filename [ format-spec ];

Ta instrukcja utworzy plik jawnie nazwany QVD, Parquet lub plik tekstowy.

Instrukcja może eksportować pola tylko z jednej tabeli danych, chyba że zachowuje się dane w formacie Parquet. W przypadku eksportowania pól z kilku tabel do pliku QVD, CSV lub TXT należy wcześniej wykonać w skrypcie jawną instrukcję join, aby utworzyć tabelę danych do wyeksportowania. Można przechowywać wiele tabel w jednym pliku Parquet, zagnieżdżając dane w plikach Parquet.

Wartości tekstowe są eksportowane do pliku CSV w formacie UTF-8 z BOM. Możliwe jest określenie ogranicznika — zobacz opis instrukcji LOAD. Instrukcja store do pliku CSV nie obsługuje eksportu BIFF.

InformacjaW niektórych przypadkach, gdy dane nie są poprawnie sformułowane, pola będą otoczone podwójnymi cudzysłowami, aby zapewnić poprawną interpretację danych. Może się tak zdarzyć na przykład wtedy, gdy pole będzie zawierać znaki takie jak cudzysłowy, przecinek, spację lub podziały wierszy.

Argumenty:

Argumenty polecenia Store

| Argument | Opis |
| --- | --- |
| fieldlist::= ( \* \| field) { , field } ) | Lista wybieranych pól. Użycie znaku \* jako listy pól oznacza wszystkie pola.<br><br>field::= fieldname [as aliasname ]<br><br>fieldname jest tekstem identycznym z nazwą pola w tabeli table. (Jeśli nazwa pola zawiera spacje lub inne znaki niestandardowe, musi być ujęta w proste podwójne cudzysłowy lub nawiasy kwadratowe).<br><br>aliasname jest alternatywną nazwą dla pola, która będzie używana w wynikowym pliku QVD lub CSV. |
| table | Etykieta skryptu reprezentująca już załadowaną tabelę do użycia jako źródło danych. |
| filename | Nazwa pliku docelowego wraz z poprawną ścieżką połączenia danych istniejącego folderu.<br><br>Przykład: 'lib://Table Files/target.qvd'<br><br>W dotychczasowym trybie tworzenia skryptów obsługiwane są również następujące formaty ścieżek:<br><br><ul> <li> <p>  bezwzględna </p> <p><span><span>Przykład: </span></span><span>c:\data\sales.qvd</span> </p> </li> <li> <p>względna wobec katalogu roboczego aplikacji <span>Qlik Sense</span>.</p> <p><span><span>Przykład: </span></span><span>data\sales.qvd</span> </p> <p>Pominięcie ścieżki spowoduje, że aplikacja <span>Qlik Sense</span> zapisze plik w katalogu wskazanym instrukcją <span>Directory</span>. W przypadku braku instrukcji <span>Directory</span> aplikacja <span>Qlik Sense</span> zapisuje plik w katalogu roboczym, którym jest <span>C:\Users\{user}\Documents\Qlik\Sense\Apps</span>. </p> </li> </ul> |
| format-spec ::=( ( txt \| qvd \| parquet), compression is codec) | Specyfikację formatu można ustawić na jeden z następujących formatów plików. Jeśli specyfikacja formatu będzie pominięta, wówczas zostanie przyjęty format qvd.<br><br><ul> <li> <p><span>txt</span> w przypadku plików <span>CSV</span> i <span>TXT</span>.</p> </li> <li> <p><span>qvd</span> dla plików <span>QVD</span>.</p> </li> <li> <p><span>parquet</span> dla plików <span>Parquet</span>.</p> </li> </ul><br><br>Jeśli używasz parquet, możesz również ustawić, który kodek kompresji ma być używany z compression is. Jeśli nie określisz kodeka z compression is, zostanie użyty kodek `snappy`. Dostępne są następujące ustawienia kompresji:<br><br><ul> <li> <p><code>uncompressed</code> </p> </li> <li> <p><code>snappy</code> </p> </li> <li> <p><code>gzip</code> </p> </li> <li> <p><code>lz4</code> </p> </li> <li> <p><code>brotli</code> </p> </li> <li> <p><code>zstd</code> </p> </li> <li> <p><code>lz4_hadoop</code> </p> </li> </ul><br><br>Przykład:<br><br>`Store mytable into [lib://AttachedFiles/myfile.parquet] (parquet, compression is lz4);` |

Przykłady:

`Store mytable into xyz.qvd 
 (qvd);` `Store * 
 from mytable into 'lib://FolderConnection/myfile.qvd';` `Store Name, RegNo from 
 mytable into xyz.qvd;` `Store Name as a, RegNo 
 as b from mytable into 'lib://FolderConnection/myfile.qvd';` `Store 
 mytable into myfile.txt (txt);` `Store mytable into [lib://FolderConnection/myfile.csv] (txt);` `Store 
 mytable into myfile.parquet (parquet);` `Store * from mytable into 
 'lib://FolderConnection/myfile.qvd';`

## Zapisywanie w plikach parquet

Parquet to format pliku o silnym typowaniu, w którym każde pole zawiera pojedynczy, określony typ danych (np. in32, double, sygnatura czasowa lub tekst). Qlik Sense przechowuje dane wewnętrzne jako słabo typowane wartości typu dual, w których dane z różnych źródeł można mieszać w tych samych polach. Ponieważ w każdym polu w pliku Parquet można przechowywać tylko jedną część wartości typu dual, ważne jest, aby wiedzieć, co zawiera każde pole. Qlik Sense używa domyślnie typu pola do określenia sposobu przechowywania tego pola. W przypadku przechowywania danych w plikach Parquet w określonym formacie należy podczas ich ładowania określić, jakiego rodzaju dane mają być Twoje pola. Jeśli spróbujesz zapisać dane w niezgodnych polach pliku Parquet, na przykład liczby w polu tekstowym lub tekst w polu znacznika czasu, otrzymasz wartości zerowe.

Podczas ładowania danych, które zamierzasz przechowywać w pliku Parquet, można zmienić domyślny sposób działania. Możesz sformatować plik tak, aby zmienić typ danych, lub dodać znacznik, aby wymusić określone typy kolumn w formacie Parquet.

### Formatowanie danych do przechowywania w pliku Parquet

Do klasyfikowania danych można używać funkcji formatowania Qlik Sense. Na przykład Text(), Num(), Interval() lub Timestamp() mogą wymuszać formaty danych podczas zapisywania danych w pliku Parquet. Qlik Sense może przechowywać dane w prawie 20 typach danych w zależności od atrybutów pól i automatycznych znaczników pól. Więcej informacji zawiera temat [Funkcje interpretacji](https://help.qlik.com/pl-PL/sense/November2024/Subsystems/Hub/Content/Sense_Hub/Scripting/InterpretationFunctions/interpretation-functions.htm).

Przykład: Formatowanie danych przy użyciu Num() i Text()

Poniższy przykład ilustruje przygotowanie danych do przechowywania w pliku Parquet. Funkcja Num() jest stosowana do pola liczbowego. Funkcję Text() stosuje się zarówno do tekstu, jak i typu mieszanego. W przypadku typu mieszanego funkcja Text() zapobiega traktowaniu go jak pola liczbowego w Parquet i zmianie wartości tekstowych na wartości null.

```

Data:
LOAD * INLINE [
num, text, mixed
123.321, abc, 123
456.654, def, xyz
789.987, ghi, 321
];

Format:NoConcatenate
LOAD num, text, Text(mixed) as mixed RESIDENT Data;
STORE Format INTO [lib://AttachedFiles/Tmp.parquet] (parquet);
```

### Oznaczanie danych w celu zapisu w pliku Parquet

Dane oznacza się znacznikami `$parquet`, aby wymusić określone typy kolumn podczas przechowywania danych w pliku Parquet. Każdy typ danych można wymusić, dodając odpowiedni znacznik sterujący. Na przykład, aby zapisać pole jako typ INT32 w pliku Parquet, oznacz je znacznikiem `$parquet-int32` w skrypcie ładowania. W zależności od typu danych będzie przechowywany ciąg znaków lub reprezentacja numeryczna danych typu dual.

Poniższych znaczników sterujących Parquet można używać do oznaczania pól do przechowywania w plikach Parquet.

Znaczniki sterujące Parquet`$parquet-int64``$parquet-float``$parquet-double``$parquet-bytearray``$parquet-bytearrayfix``$parquet-decimal``$parquet-date``$parquet-time``$parquet-timestamp``$parquet-string``$parquet-enum``$parquet-interval``$parquet-json``$parquet-bson``$parquet-uuid`

| Znacznik sterujący | Dual | Typ fizyczny | Typ logiczny | Przekształcony typ |
| --- | --- | --- | --- | --- |
| `$parquet-boolean` | Liczba | BOOLEAN | NONE | NONE |
| `$parquet-int32` | Liczba | INT32 | NONE | NONE |
| Liczba | INT64 | NONE | NONE |  |
| Liczba | FLOAT | NONE | NONE |  |
| Liczba | DOUBLE | NONE | NONE |  |
| Ciąg znaków | BYTE\_ARRAY | NONE | UTF8 |  |
| Liczba | FIXED\_LEN\_BYTE\_ARRAY | NONE | DECIMAL |  |
| Liczba | INT64 | DECIMAL | DECIMAL |  |
| Liczba | INT32 | DATE | DATE |  |
| Liczba | INT64 | TIME | TIME\_MICROS |  |
| Liczba | INT64 | TIMESTAMP | TIMESTAMP\_MICROS |  |
| Ciąg znaków | BYTE\_ARRAY | STRING | UTF8 |  |
| Ciąg znaków | BYTE\_ARRAY | ENUM | ENUM |  |
| Liczba | FIXED\_LEN\_BYTE\_ARRAY | INTERVAL | INTERVAL |  |
| Ciąg znaków | BYTE\_ARRAY | JSON | JSON |  |
| Ciąg znaków | BYTE\_ARRAY | BSON | BSON |  |
| Ciąg znaków | FIXED\_LEN\_BYTE\_ARRAY | UUID | NONE |  |

Przykład: Oznaczanie danych w celu zapisu w pliku Parquet

W tym przykładzie dwa znaczniki służą do definiowania danych dla formatu Parquet. Pole num jest oznaczone znacznikiem `$parquet-int32` w celu zdefiniowania go jako pola liczbowego, które w pliku Parquet zostanie ustawione jako INT32.

```

Data:
LOAD * INLINE [
num, text, 
123.321, abc
456.654, def 
789.987, ghi 
];
TAG num WITH '$parquet-int32';
STORE Format INTO [lib://AttachedFiles/Tmp.parquet] (parquet);
```

### Przechowywanie zagnieżdżonych danych w plikach Parquet

Możesz przechowywać wiele tabel w plikach Parquet, zagnieżdżając je w uporządkowanych danych. Store obsługuje ustrukturyzowane węzły i węzły w formie listy w schemacie gwiazdy. Pojedyncze tabele można również przechowywać w trybie zagnieżdżonym, używając określenia Ogranicznikiem jest.

Podczas zapisywania tabel określ tabele, które chcesz uwzględnić, oddzielając je przecinkami. Na przykład: `STORE Table1, Table2, Table3 INTO [lib://<file location>/<file name>.parquet] (parquet);`. Możesz kontrolować, które pola mają być zachowane, korzystając z listy pól w instrukcji Store. Na przykład `STORE Field1, Field2, FROM Table1, Table2 INTO [lib://<file location>/<file name>.parquet] (parquet);`. Wszystkie pola na liście pól muszą znajdować się w co najmniej jednej z wymienionych tabel. Pierwsza tabela w instrukcji Store zostanie użyta jako tabela faktów w schemacie gwiaździstym.

Nazwy pól służą do kontrolowania sposobu tworzenia i zagnieżdżania grup. Domyślnie nazwy pól są dzielone na węzły za pomocą kropki (`.`). Separator można zmienić, ustawiając zmienną systemową FieldNameDelimiter lub używając specyfikatora Delimiter is. Specyfikator spowoduje zastąpienie zmiennej systemowej. Aby uzyskać więcej informacji, zobacz temat [Praca ze zmiennymi w edytorze ładowania danych](https://help.qlik.com/pl-PL/sense/November2024/Subsystems/Hub/Content/Sense_Hub/Scripting/work-with-variables-in-data-load-editor.htm).

Nazwy pól są oddzielane separatorem, a poszczególne części służą do tworzenia schematu z zagnieżdżonymi grupami. Na przykład instrukcja `STORE Field1, Field1.Field2, Field1.Field3, Field1.Field4 FROM Table1 INTO [nested.parquet] (parquet, delimiter is '.');` utworzy dwie grupy (Group1 i Group2) z Field1, Field2 i Field3, Field4.

InformacjaGrupy i pola nie mogą mieć tej samej nazwy w węźle schematu. Na przykład instrukcja `STORE Address, Address.Street INTO [nested.parquet] (parquet, delimiter is '.'');` zakończy się niepowodzeniem, ponieważ Adres jest niejednoznaczny i jest zarówno polem danych, jak i grupą.

Podczas przechowywania zagnieżdżonych danych w formacie Parquet klucze między tabelami są przekształcane w węzły łączy w schemacie. Tabele są przekształcane w ustrukturyzowane węzły w schemacie. Domyślną transformację można zastąpić za pomocą nazw pól.

Przykład: Przechowywanie zagnieżdżonych danych w pliku Parquet

```

company:
LOAD * INLINE [
company, contact
A&G, Amanda Honda
Cabro, Cary Frank
Fenwick, Dennis Fisher
Camros, Molly McKenzie
];

salesrep:
LOAD * INLINE [
company, salesrep
A&G, Bob Park
Cabro, Cezar Sandu
Fenwick, Ken Roberts
Camros, Max Smith
];

headquarter:
LOAD * INLINE [
company, country, city
A&G, USA, Los Angeles
Cabro, USA, Albuquerque
Fenwick, USA, Baltimore
Camros, USA, Omaha
];

region:
LOAD * INLINE [
region, city
West, Los Angeles
Southwest, Albuquerque
East, Baltimore
Central, Omaha
];


STORE company, salesrep, headquarter, region INTO [lib://AttachedFiles/company.parquet] (parquet)
DROP TABLES company, salesrep, headquarter, region;
```

Wynikowy plik Parquet ma następujący schemat:

```

company (String)
contact (String)
company:salesrep (List)
	salesrep (Group)
		salesrep (String)
company:headquarter (List)
	headquarter (Group)
		country (String)
		city (String)
		city:region (List)
			region (Group)
				region (String)
```

#### Ograniczenia

Przechowywanie zagnieżdżonych danych w formacie Parquet ma następujące ograniczenia:

* Operacja Store nie obsługuje węzłów mapy.

* Przechowywanie nie obejmuje pól klucza generowanych w wyniku ładowania zagnieżdżonych plików Parquet.

* Nie można przechowywać razem danych z tabel, które nie są powiązane z polami klucza.

* Zagnieżdżony plik denormalizuje model danych. Wartości, do których nie ma odniesień, nie zostaną zapisane, a wartości, do których istnieje wiele odwołań, zostaną skopiowane.