Comment définir des variables dans les scripts HIVE

102

Je recherche l'équivalent SQL de SET varname = valuedans Hive QL

Je sais que je peux faire quelque chose comme ça:

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

Mais alors j'obtiens cette erreur:

le caractère «@» n'est pas pris en charge ici

user1678312
la source
Malheureusement, il n'existe aucun moyen sûr de définir une variable de chaîne car si quelqu'un exécute la requête sans définir la variable, la chaîne utilisera simplement l'appel de variable comme chaîne. :(
combinatorist

Réponses:

201

Vous devez utiliser le hiveconf spécial pour la substitution de variables. par exemple

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

de même, vous pouvez passer en ligne de commande:

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

Notez qu'il existe également des variables env et système , vous pouvez donc y faire référence ${env:USER}par exemple.

Pour voir toutes les variables disponibles, à partir de la ligne de commande, exécutez

% hive -e 'set;'

ou à partir de l'invite de la ruche, exécutez

hive> set;

Mise à jour: J'ai également commencé à utiliser des variables hivevar , en les plaçant dans des extraits de code hql que je peux inclure à partir de la CLI de la ruche en utilisant la sourcecommande (ou en passant l'option -i à partir de la ligne de commande). L'avantage ici est que la variable peut ensuite être utilisée avec ou sans le préfixe hivevar, et permettre quelque chose qui s'apparente à une utilisation globale ou locale.

Donc, supposons que vous ayez un fichier setup.hql qui définit une variable de nom de table :

set hivevar:tablename=mytable;

alors, je peux mettre en ruche:

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

et utiliser dans la requête:

hive> select * from ${tablename}

ou

hive> select * from ${hivevar:tablename}

Je pourrais également définir un nom de table "local", ce qui affecterait l'utilisation de $ {nom_table}, mais pas de $ {hivevar: nom_table}

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

contre

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

Cela ne veut probablement pas dire trop de la CLI, mais peut avoir hql dans un fichier qui utilise la source , mais définir certaines des variables "localement" à utiliser dans le reste du script.

libjack
la source
1
Cela passe un paramètre de la ligne de commande. Je développe des requêtes dans Karmasphere et je dois définir quelques contants dans la mendicité afin que je ne code pas en dur les dates 10 fois dans mon script. Est-ce que quelque chose comme ça est possible?
user1678312
fonctionne dans les deux sens, si vous le faites, set CURRENT_DATE='2012-09-16';vous pouvez vous y référer plus tard avec${hiveconf:CURRENT_DATE}
libjack
1
Comment cela fonctionne-t-il si plusieurs tâches Hive sont exécutées simultanément? Vont-ils finir par récupérer des valeurs les uns des autres? Dans l'automatisation, je construis un fichier HQL en le faisant précéder de quelques instructions SET. Je veux m'assurer que si je soumets deux travaux en même temps qui utilisent les mêmes noms de variables, un travail ne récupérera pas les valeurs de l'autre travail. La sémantique ici n'est pas claire d'après votre réponse.
MattD
5
cela fonctionne pour moi sur le serveur Hive. Cependant, j'ai configuré des tests d'intégration sur une machine locale dans IntelliJ. Je continue à recevoir l'erreur suivante en essayant d'utiliser la variable de cette façon:FAILED: ParseException line x:y cannot recognize input near '$' '{' 'hiveconf' in expression specification
chepukha
1
@DatabaseCoder À ma connaissance, rien de tel ne fonctionnera. Chaque fois que j'ai besoin de quelque chose comme ça, je dois faire la première requête, puis passer via "--hiveconf"
libjack
21

La plupart des réponses ici ont suggéré d'utiliser hiveconfou d' hivevarespace de noms pour stocker la variable. Et toutes ces réponses sont justes. Cependant, il existe un autre espace de noms.

Il y en a au total trois namespacesdisponibles pour contenir des variables.

  1. hiveconf - hive a commencé avec ceci, toute la configuration de la ruche est stockée dans le cadre de cette conf. Au départ, la substitution de variables ne faisait pas partie de la ruche et lorsqu'elle a été introduite, toutes les variables définies par l'utilisateur ont également été stockées dans ce cadre. Ce n'est certainement pas une bonne idée. Donc, deux autres espaces de noms ont été créés.
  2. hivevar : pour stocker des variables utilisateur
  3. system : pour stocker les variables système.

Et donc, si vous stockez une variable dans le cadre d'une requête (c'est-à-dire date ou numéro_produit), vous devez utiliser l' hivevarespace de noms et non l' hiveconfespace de noms.

Et voici comment cela fonctionne.

hiveconf est toujours l' espace de noms par défaut , donc si vous ne fournissez aucun espace de noms, il stockera votre variable dans l'espace de noms hiveconf.

Cependant, quand il s'agit de référencer une variable, ce n'est pas vrai. Par défaut, il fait référence à l' espace de noms hivevar . Confus, non? Cela peut devenir plus clair avec l'exemple suivant.

Si vous ne fournissez pas d'espace de noms comme mentionné ci-dessous, la variable varsera stockée dans l' hiveconfespace de noms.

set var="default_namespace";

Donc, pour y accéder, vous devez spécifier l' hiveconf espace de noms

select ${hiveconf:var};

Et si vous ne fournissez pas d'espace de noms, cela vous donnera une erreur comme mentionné ci-dessous, la raison étant que, par défaut, si vous essayez d'accéder à une variable, elle ne vérifie que dans l' hivevarespace de noms. Et hivevaril n'y a pas de variable nomméevar

select ${var}; 

Nous avons explicitement fourni un hivevarespace de noms

set hivevar:var="hivevar_namespace";

comme nous fournissons l'espace de noms, cela fonctionnera.

select ${hivevar:var}; 

Et par défaut, l'espace de travail utilisé lors de la référence d'une variable est hivevar, ce qui suit fonctionnera également.

select ${var};
Gaurang Shah
la source
7

Avez-vous essayé d'utiliser le signe dollar et les parenthèses comme ceci:

SELECT * 
FROM foo 
WHERE day >= '${CURRENT_DATE}';
YABADABADOU
la source
C'est la seule réponse qui fonctionne pour moi. Les guillemets sont obligatoires dans mon interface de ruche ambari.
Laurens Koppenol
il y a deux choses hivevar et hiveconf - les deux sont expliquées en détail ici
Rahul Sharma
3

Deux moyens simples:

Utilisation de la configuration de la ruche

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

Utilisation des var de la ruche

Sur votre ensemble de CLI, utilisez-les dans la ruche

set hivevar:USER_NAME='FOO';

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

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

Savio D'Souza
la source
2

Une chose à garder à l'esprit est de définir des chaînes, puis de s'y référer. Vous devez vous assurer que les citations ne se heurtent pas.

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

Lorsque vous définissez des dates, faites-leur référence dans le code car les chaînes peuvent entrer en conflit. Cela ne fonctionnerait pas avec le set start_date ci-dessus.

 '${hiveconf:start_date}'

Nous devons garder à l'esprit de ne pas définir deux guillemets simples ou doubles pour les chaînes lorsque vous vous y référez dans la requête.

blondie9x
la source
2

Juste au cas où quelqu'un aurait besoin de paramétrer la requête de la ruche via cli.

Par exemple:

hive_query.sql

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

Maintenant, exécutez le fichier sql ci-dessus à partir de cli:

hive --hivevar CURRENT_DATE="2012-09-16" -f hive_query.sql
Abdul Mannan
la source
0

Essayez cette méthode:

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

cela fonctionne bien sur ma plateforme.

typhoonbxq
la source
0

Vous pouvez exporter la variable dans le script shell export CURRENT_DATE = "2012-09-16"

Ensuite, dans hiveql, vous aimez SELECT * FROM foo WHERE day> = '$ {env: CURRENT_DATE}'

Dileep Dominic
la source
-7

Vous pouvez stocker la sortie d'une autre requête dans une variable et cette dernière vous pouvez utiliser la même chose dans votre code:

set var=select count(*) from My_table;
${hiveconf:var};
Suman
la source
Vous vous trompez, sélectionnez count (*) dans My_table; sera stocké dans var .
Ilya Bystrov