So legen Sie Variablen in HIVE-Skripten fest


101

Ich suche das SQL-Äquivalent von SET varname = valuein Hive QL

Ich weiß, dass ich so etwas tun kann:

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

Aber dann bekomme ich diesen Fehler:

Zeichen '@' wird hier nicht unterstützt


Leider gibt es keine sichere Möglichkeit, eine Zeichenfolgenvariable festzulegen. Wenn jemand die Abfrage ohne Festlegen der Variablen ausführt, verwendet die Zeichenfolge den Variablenaufruf einfach als Zeichenfolge. :(
Kombinator

Antworten:


200

Sie müssen die spezielle Hiveconf für die Variablensubstitution verwenden. z.B

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

Ebenso können Sie die Befehlszeile weitergeben:

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

Beachten Sie, dass es auch env- und Systemvariablen gibt , auf die Sie ${env:USER}beispielsweise verweisen können .

Führen Sie die Befehlszeile aus, um alle verfügbaren Variablen anzuzeigen

% hive -e 'set;'

oder führen Sie an der Eingabeaufforderung "Hive" aus

hive> set;

Update: Ich habe begonnen, auch Hivevar- Variablen zu verwenden und sie in HQL-Snippets einzufügen, die ich mithilfe des sourceBefehls aus der Hive-CLI einschließen kann (oder als -i-Option über die Befehlszeile übergeben kann). Der Vorteil hierbei ist, dass die Variable dann mit oder ohne das Präfix hivevar verwendet werden kann und eine ähnliche globale oder lokale Verwendung zulässt.

Nehmen wir also an, Sie haben eine setup.hql, die eine Tabellennamenvariable setzt:

set hivevar:tablename=mytable;

dann kann ich in den Bienenstock bringen:

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

und in Abfrage verwenden:

hive> select * from ${tablename}

oder

hive> select * from ${hivevar:tablename}

Ich könnte auch einen "lokalen" Tabellennamen festlegen, der sich auf die Verwendung von $ {Tabellenname} auswirkt, nicht jedoch auf $ {hivevar: Tabellenname}

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

vs.

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

Bedeutet wahrscheinlich nicht zu viel von der CLI, kann aber hql in einer Datei haben, die den Quellcode verwendet , aber einige der Variablen "lokal" festlegen, um sie im Rest des Skripts zu verwenden.


1
Dies ist die Übergabe eines Parameters über die Befehlszeile. Ich entwickle Abfragen in Karmasphere und muss beim Betteln einige Contants festlegen, damit ich in meinem Skript keine 10-mal harten Codedaten habe. Ist so etwas möglich?
user1678312

funktioniert in beide Richtungen, wenn Sie dies tun set CURRENT_DATE='2012-09-16';, können Sie später mit${hiveconf:CURRENT_DATE}
libjack

1
Wie funktioniert das, wenn mehrere Hive-Jobs gleichzeitig ausgeführt werden? Werden sie am Ende Werte voneinander aufnehmen? In der Automatisierung erstelle ich eine HQL-Datei, indem ich ihr einige SET-Anweisungen voranstelle. Ich möchte sicherstellen, dass ein Job keine Werte vom anderen Job aufnimmt, wenn ich zwei Jobs gleichzeitig sende, die dieselben Variablennamen verwenden. Die Semantik hier ist aus Ihrer Antwort nicht klar.
MattD

5
Das funktioniert bei mir auf dem Hive-Server. Ich habe jedoch einige Integrationstests auf einem lokalen Computer in IntelliJ eingerichtet. Ich erhalte immer wieder den folgenden Fehler, wenn ich versuche, eine Variable auf diese Weise zu verwenden:FAILED: ParseException line x:y cannot recognize input near '$' '{' 'hiveconf' in expression specification
Chepukha

1
@DatabaseCoder Meines Wissens wird so etwas nicht funktionieren. Wann immer ich so etwas brauche, muss ich die erste Abfrage machen und dann über "--hiveconf"
libjack

20

Die meisten Antworten hier haben vorgeschlagen, entweder hiveconfoder einen hivevarNamespace zum Speichern der Variablen zu verwenden. Und all diese Antworten sind richtig. Es gibt jedoch noch einen Namespace.

namespacesFür das Halten von Variablen stehen insgesamt drei zur Verfügung.

  1. hiveconf - hive begann damit, die gesamte Hive-Konfiguration wird als Teil dieser Conf gespeichert. Anfänglich war die Variablensubstitution nicht Teil von Hive, und als sie eingeführt wurde, wurden auch alle benutzerdefinierten Variablen als Teil davon gespeichert. Welches ist definitiv keine gute Idee. So wurden zwei weitere Namespaces erstellt.
  2. hivevar : Zum Speichern von Benutzervariablen
  3. System : Zum Speichern von Systemvariablen.

Wenn Sie also eine Variable als Teil einer Abfrage speichern (dh Datum oder Produktnummer), sollten Sie den hivevarNamespace und nicht den hiveconfNamespace verwenden.

Und so funktioniert es.

hiveconf ist immer noch der Standard-Namespace . Wenn Sie also keinen Namespace angeben, wird Ihre Variable im hiveconf-Namespace gespeichert.

Wenn es jedoch darum geht, eine Variable zu referenzieren, ist dies nicht der Fall. Standardmäßig bezieht es sich auf den Hivevar- Namespace. Verwirrend, richtig? Mit dem folgenden Beispiel kann dies klarer werden.

Wenn Sie keinen Namespace wie unten angegeben angeben, wird die Variable varim hiveconfNamespace gespeichert .

set var="default_namespace";

Um darauf zugreifen zu können, müssen Sie einenhiveconf Namespace angeben

select ${hiveconf:var};

Wenn Sie keinen Namespace angeben , wird ein Fehler angezeigt, wie unten erwähnt. Dies liegt daran, dass beim Versuch, auf eine Variable zuzugreifen, standardmäßig hivevarnur der Namespace überprüft wird . Und darin hivevarist keine Variable benanntvar

select ${var}; 

Wir haben den hivevarNamespace explizit angegeben

set hivevar:var="hivevar_namespace";

Da wir den Namespace bereitstellen, funktioniert dies.

select ${hivevar:var}; 

Standardmäßig wird beim Verweisen auf eine Variable hivevarder folgende Arbeitsbereich verwendet .

select ${var};

7

Haben Sie versucht, das Dollarzeichen und die Klammern wie folgt zu verwenden:

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

Dies ist die einzige funktionierende Antwort für mich. Die Anführungszeichen werden in meiner Ambari-Hive-Oberfläche benötigt.
Laurens Koppenol

Es gibt zwei Dinge, Hivevar und Hiveconf - beide werden hier
Rahul Sharma

3

Zwei einfache Möglichkeiten:

Mit hive conf

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

Hive Vars verwenden

Stellen Sie auf Ihrer CLI vars ein und verwenden Sie sie dann in hive

set hivevar:USER_NAME='FOO';

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

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


2

Eine Sache, die Sie beachten sollten, ist, Zeichenfolgen zu setzen und dann auf sie zurückzugreifen. Sie müssen sicherstellen, dass die Anführungszeichen nicht kollidieren.

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

Wenn Sie Datumsangaben festlegen, beziehen Sie sich im Code auf diese, da die Zeichenfolgen Konflikte verursachen können. Dies würde mit dem oben eingestellten start_date nicht funktionieren.

 '${hiveconf:start_date}'

Wir müssen darauf achten, keine doppelten einfachen oder doppelten Anführungszeichen für Zeichenfolgen zu setzen, wenn wir in der Abfrage darauf zurückgreifen.


2

Nur für den Fall, dass jemand die Hive-Abfrage über CLI parametrisieren muss.

Zum Beispiel:

hive_query.sql

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

Führen Sie nun die obige SQL-Datei von cli aus:

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

0

Versuchen Sie diese Methode:

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

es funktioniert gut auf meiner Plattform.


0

Sie können die Variable im Shell-Skript exportieren. Export CURRENT_DATE = "2012-09-16"

Dann magst du in hiveql SELECT * FROM foo WHERE day> = '$ {env: CURRENT_DATE}'


-7

Sie können die Ausgabe einer anderen Abfrage in einer Variablen speichern und letztere in Ihrem Code verwenden:

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

Wenn Sie sich irren, wählen Sie count (*) aus My_table. wird in var gespeichert .
Ilya Bystrov
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.