Jak ustawić zmienne w skryptach HIVE


102

Szukam odpowiednika SQL SET varname = valuew Hive QL

Wiem, że mogę zrobić coś takiego:

SET CURRENT_DATE = '2012-09-16';
SELECT * FROM foo WHERE day >= @CURRENT_DATE

Ale potem pojawia się ten błąd:

znak „@” nie jest tutaj obsługiwany


Niestety, nie ma bezpiecznego sposobu na ustawienie zmiennej łańcuchowej, ponieważ jeśli ktoś uruchomi zapytanie bez ustawiania zmiennej, łańcuch po prostu użyje wywołania zmiennej jako łańcucha. :(
combinatorist

Odpowiedzi:


202

Do podstawiania zmiennych musisz użyć specjalnego hiveconf . na przykład

hive> set CURRENT_DATE='2012-09-16';
hive> select * from foo where day >= '${hiveconf:CURRENT_DATE}'

podobnie możesz przekazać w wierszu poleceń:

% hive -hiveconf CURRENT_DATE='2012-09-16' -f test.hql

Zauważ, że istnieją również zmienne env i systemowe , więc możesz ${env:USER}na przykład odwołać się .

Aby zobaczyć wszystkie dostępne zmienne, z wiersza poleceń uruchom

% hive -e 'set;'

lub w wierszu polecenia ula, uruchom

hive> set;

Aktualizacja: Zacząłem również używać zmiennych hivevar , umieszczając je we fragmentach hql, które mogę dołączyć z hive CLI za pomocą sourcepolecenia (lub przekazać jako opcję -i z wiersza poleceń). Zaletą jest to, że zmienna może być następnie używana z prefiksem hivevar lub bez niego i umożliwia użycie czegoś zbliżonego do użycia globalnego lub lokalnego.

Załóżmy więc, że mamy plik setup.hql, który ustawia zmienną nazwy tabeli :

set hivevar:tablename=mytable;

wtedy mogę wnieść do ula:

hive> source /path/to/setup.hql;

i użyj w zapytaniu:

hive> select * from ${tablename}

lub

hive> select * from ${hivevar:tablename}

Mógłbym również ustawić „lokalną” nazwę tabeli, co wpłynęłoby na użycie $ {tablename}, ale nie $ {hivevar: tablename}

hive> set tablename=newtable;
hive> select * from ${tablename} -- uses 'newtable'

vs

hive> select * from ${hivevar:tablename} -- still uses the original 'mytable'

Prawdopodobnie nie znaczy to zbyt wiele z CLI, ale może mieć hql w pliku, który używa źródła , ale ustawia niektóre zmienne „lokalnie” do użycia w pozostałej części skryptu.


1
To jest przekazywanie parametru z wiersza poleceń. Tworzę zapytania w Karmasphere i muszę ustawić kilka elementów na początku, aby nie zakodować dat w moim skrypcie 10 razy. Czy coś takiego jest możliwe?
user1678312

działa w obie strony, jeśli to zrobisz set CURRENT_DATE='2012-09-16';, możesz odnieść się do tego później${hiveconf:CURRENT_DATE}
libjack

1
Jak to działa, jeśli mam jednocześnie uruchomionych wiele zadań Hive? Czy ostatecznie przejmą od siebie wartości? W automatyzacji konstruuję plik HQL, poprzedzając go kilkoma instrukcjami SET. Chcę się upewnić, że jeśli prześlę jednocześnie dwa zadania, które używają tych samych nazw zmiennych, jedno zadanie nie pobierze wartości z innego zadania. Ta semantyka nie jest jasna z twojej odpowiedzi.
MattD

5
to działa dla mnie na serwerze Hive. Jednak skonfigurowałem kilka testów integracji na komputerze lokalnym w IntelliJ. Podczas próby użycia zmiennej w ten sposób FAILED: ParseException line x:y cannot recognize input near '$' '{' 'hiveconf' in expression specification
pojawia

1
@DatabaseCoder O ile wiem, nic takiego nie zadziała. Zawsze, gdy potrzebuję czegoś takiego, muszę wykonać pierwsze zapytanie, a następnie przekazać przez „--hiveconf”
libjack.

21

Większość odpowiedzi sugeruje użycie hiveconflub hivevarprzestrzeni nazw do przechowywania zmiennej. Wszystkie te odpowiedzi są prawidłowe. Jest jednak jeszcze jedna przestrzeń nazw.

Dostępne są łącznie trzy namespaceszmienne do przechowywania.

  1. hiveconf - gałąź zaczęła się od tego, cała konfiguracja gałęzi jest przechowywana jako część tego ustawienia. Początkowo podstawianie zmiennych nie było częścią gałęzi, a kiedy zostało wprowadzone, wszystkie zmienne zdefiniowane przez użytkownika były również przechowywane w ramach tego. Co zdecydowanie nie jest dobrym pomysłem. Utworzono więc dwie kolejne przestrzenie nazw.
  2. hivevar : do przechowywania zmiennych użytkownika
  3. system : do przechowywania zmiennych systemowych.

Jeśli więc przechowujesz zmienną jako część zapytania (np. Datę lub numer_produktu), powinieneś używać hivevarprzestrzeni nazw, a nie hiveconfprzestrzeni nazw.

I tak to działa.

hiveconf jest nadal domyślną przestrzenią nazw , więc jeśli nie podasz żadnej przestrzeni nazw, będzie przechowywać zmienną w przestrzeni nazw hiveconf.

Jednak jeśli chodzi o odwoływanie się do zmiennej, to nieprawda. Domyślnie odnosi się do przestrzeni nazw hivevar . Mylące, prawda? Może to stać się jaśniejsze na następującym przykładzie.

Jeśli nie podasz przestrzeni nazw, jak wspomniano poniżej, zmienna varbędzie przechowywana w hiveconfprzestrzeni nazw.

set var="default_namespace";

Tak więc, aby uzyskać do niego dostęp, musisz określić hiveconf przestrzeń nazw

select ${hiveconf:var};

A jeśli nie podasz przestrzeni nazw , spowoduje to błąd, jak wspomniano poniżej, ponieważ domyślnie, jeśli spróbujesz uzyskać dostęp do zmiennej, sprawdza ona hivevartylko w przestrzeni nazw. I hivevarnie ma zmiennej o nazwievar

select ${var}; 

Udostępniliśmy jawnie hivevarprzestrzeń nazw

set hivevar:var="hivevar_namespace";

ponieważ zapewniamy przestrzeń nazw, to zadziała.

select ${hivevar:var}; 

Domyślnie obszar roboczy używany podczas odwoływania się do zmiennej to hivevar, poniższe również będą działać.

select ${var};

7

Czy próbowałeś użyć znaku dolara i nawiasów w ten sposób:

SELECT * 
FROM foo 
WHERE day >= '${CURRENT_DATE}';

To dla mnie jedyna działająca odpowiedź. Cytaty są wymagane w moim interfejsie hive ambari.
Laurens Koppenol,

są dwie rzeczy hivevar i hiveconf - obie są szczegółowo wyjaśnione tutaj
Rahul Sharma


2

Jedną rzeczą, o której należy pamiętać, jest ustawienie łańcuchów, a następnie odwołanie się do nich. Musisz się upewnić, że cytaty się nie kolidują.

 set start_date = '2019-01-21';
 select ${hiveconf:start_date}; 

Podczas ustawiania dat odwołujemy się do nich w kodzie, ponieważ ciągi znaków mogą powodować konflikty. To nie zadziała z ustawioną powyżej datą_początkową.

 '${hiveconf:start_date}'

Musimy pamiętać, aby nie ustawiać podwójnych apostrofów lub podwójnych cudzysłowów dla ciągów podczas odwoływania się do nich w zapytaniu.


2

Na wypadek, gdyby ktoś musiał sparametryzować zapytanie gałęzi przez CLI.

Na przykład:

hive_query.sql

SELECT * FROM foo WHERE day >= '${hivevar:CURRENT_DATE}'

Teraz wykonaj powyższy plik sql z cli:

hive --hivevar CURRENT_DATE="2012-09-16" -f hive_query.sql

0

Wypróbuj tę metodę:

set t=20;
select *
from myTable
where age > '${hiveconf:t}'; 

działa dobrze na mojej platformie.


0

Możesz wyeksportować zmienną za pomocą eksportu skryptu powłoki CURRENT_DATE = "2012-09-16"

Następnie w hiveql lubisz SELECT * FROM foo WHERE day> = '$ {env: CURRENT_DATE}'


-7

Możesz przechowywać wyniki innego zapytania w zmiennej, a później możesz użyć tego samego w swoim kodzie:

set var=select count(*) from My_table;
${hiveconf:var};

Mylisz się, wybierz count (*) z My_table; będzie przechowywany w var .
Ilya Bystrov
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.