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

user1678312
źródło
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.

libjack
źródło
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};
Gaurang Shah
źródło
7

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

SELECT * 
FROM foo 
WHERE day >= '${CURRENT_DATE}';
YABADABADOU
źródło
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
3

Dwa proste sposoby:

Korzystanie z konf. Ula

hive> set USER_NAME='FOO';
hive> select * from foobar where NAME = '${hiveconf:USER_NAME}';

Używanie vars ula

Na swoim CLI ustaw vars, a następnie użyj ich w ulu

set hivevar:USER_NAME='FOO';

hive> select * from foobar where NAME = '${USER_NAME}';
hive> select * from foobar where NAME = '${hivevar:USER_NAME}';

Dokumentacja: https://cwiki.apache.org/confluence/display/Hive/LanguageManual+VariableSubstitution

Savio D'Souza
źródło
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.

blondie9x
źródło
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
Abdul Mannan
źródło
0

Wypróbuj tę metodę:

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

działa dobrze na mojej platformie.

typhoonbxq
źródło
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}'

Dileep Dominic
źródło
-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};
Suman
źródło
Mylisz się, wybierz count (*) z My_table; będzie przechowywany w var .
Ilya Bystrov