Cómo establecer variables en scripts de HIVE

102

Estoy buscando el equivalente SQL de SET varname = valueen Hive QL

Sé que puedo hacer algo como esto:

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

Pero luego me sale este error:

el carácter '@' no se admite aquí

usuario1678312
fuente
Desafortunadamente, no existe una forma segura de establecer una variable de cadena porque si alguien ejecuta la consulta sin establecer la variable, la cadena simplemente usará la llamada a la variable como una cadena. :(
combinatorist

Respuestas:

201

Necesita usar el hiveconf especial para la sustitución de variables. p.ej

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

de manera similar, puede pasar la línea de comando:

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

Tenga en cuenta que también hay variables env y system , por lo que puede hacer referencia, ${env:USER}por ejemplo,.

Para ver todas las variables disponibles, desde la línea de comando, ejecute

% hive -e 'set;'

o desde el indicador de colmena, ejecute

hive> set;

Actualización: también comencé a usar variables de hivevar , poniéndolas en fragmentos de hql que puedo incluir desde la CLI de hive usando el sourcecomando (o pasar como opción -i desde la línea de comando). El beneficio aquí es que la variable se puede usar con o sin el prefijo hivevar, y permitir algo similar al uso global vs local.

Entonces, suponga que tiene setup.hql que establece una variable de nombre de tabla:

set hivevar:tablename=mytable;

entonces, puedo traer a la colmena:

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

y usar en la consulta:

hive> select * from ${tablename}

o

hive> select * from ${hivevar:tablename}

También podría establecer un nombre de tabla "local", que afectaría el uso de $ {nombre de tabla}, pero no $ {hivevar: nombre de tabla}

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

vs

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

Probablemente no signifique mucho de la CLI, pero puede tener hql en un archivo que usa fuente , pero establezca algunas de las variables "localmente" para usar en el resto del script.

libjack
fuente
1
Esto es pasar un parámetro desde la línea de comando. Estoy desarrollando consultas en Karmasphere y necesito establecer algunos contants al principio para no codificar fechas 10 veces en mi script. ¿Es posible algo así?
user1678312
funciona en ambos sentidos, si lo hace set CURRENT_DATE='2012-09-16';, puede consultarlo más tarde con${hiveconf:CURRENT_DATE}
libjack
1
¿Cómo funciona esto si tengo varios trabajos de Hive ejecutándose simultáneamente? ¿Terminarán recogiendo valores unos de otros? En automatización, estoy construyendo un archivo HQL anteponiéndolo con algunas declaraciones SET. Quiero asegurarme de que si envío dos trabajos al mismo tiempo que usan los mismos nombres de variable, un trabajo no recogerá valores del otro trabajo. La semántica aquí no está clara a partir de su respuesta.
MattD
5
esto funciona para mí en el servidor Hive. Sin embargo, configuré algunas pruebas de integración en la máquina local en IntelliJ. Sigo recibiendo el siguiente error cuando intento usar la variable de esta manera:FAILED: ParseException line x:y cannot recognize input near '$' '{' 'hiveconf' in expression specification
chepukha
1
@DatabaseCoder Que yo sepa, nada de eso funcionará. Siempre que necesito algo así, tengo que hacer la primera consulta y luego pasar a través de "--hiveconf"
libjack
21

La mayoría de las respuestas aquí han sugerido usar hiveconfo el hivevarespacio de nombres para almacenar la variable. Y todas esas respuestas son correctas. Sin embargo, hay un espacio de nombres más.

Hay un total de tres namespacesdisponibles para mantener variables.

  1. hiveconf - hive comenzó con esto, toda la configuración de hive se almacena como parte de esta conf. Inicialmente, la sustitución de variables no formaba parte de Hive y cuando se introdujo, todas las variables definidas por el usuario también se almacenaron como parte de esto. Lo que definitivamente no es una buena idea. Entonces se crearon dos espacios de nombres más.
  2. hivevar : para almacenar variables de usuario
  3. sistema : para almacenar variables del sistema.

Entonces, si está almacenando una variable como parte de una consulta (es decir, fecha o número de producto), debe usar el hivevarespacio de nombres y no el hiveconfespacio de nombres.

Y así es como funciona.

hiveconf sigue siendo el espacio de nombres predeterminado , por lo que si no proporciona ningún espacio de nombres, almacenará su variable en el espacio de nombres hiveconf.

Sin embargo, cuando se trata de referir una variable, no es cierto. De forma predeterminada, se refiere al espacio de nombres hivevar . Confuso, ¿verdad? Puede resultar más claro con el siguiente ejemplo.

Si no proporciona el espacio de nombres como se menciona a continuación, la variable varse almacenará en el hiveconfespacio de nombres.

set var="default_namespace";

Entonces, para acceder a esto, debe especificar el hiveconf espacio de nombres

select ${hiveconf:var};

Y si no proporciona un espacio de nombres , le dará un error como se menciona a continuación, por lo que, de forma predeterminada, si intenta acceder a una variable, solo verifica el hivevarespacio de nombres. Y hivevarno hay una variable nombradavar

select ${var}; 

Hemos proporcionado explícitamente un hivevarespacio de nombres

set hivevar:var="hivevar_namespace";

ya que estamos proporcionando el espacio de nombres, esto funcionará.

select ${hivevar:var}; 

Y de forma predeterminada, el espacio de trabajo utilizado durante la referencia de una variable es hivevarel siguiente también funcionará.

select ${var};
Gaurang Shah
fuente
7

¿Ha intentado usar el signo de dólar y corchetes como este?

SELECT * 
FROM foo 
WHERE day >= '${CURRENT_DATE}';
YABADABADOU
fuente
Esta es la única respuesta que funciona para mí. Las citas son necesarias en la interfaz de mi colmena ambari.
Laurens Koppenol
hay dos cosas hivevar y hiveconf, ambas se explican en detalle aquí
Rahul Sharma
3

Dos formas sencillas:

Usando Hive Conf

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

Usando vars de colmena

En su CLI, configure vars y luego utilícelas en Hive

set hivevar:USER_NAME='FOO';

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

Documentación: https://cwiki.apache.org/confluence/display/Hive/LanguageManual+VariableSubstitution

Savio D'Souza
fuente
2

Una cosa a tener en cuenta es establecer cadenas y luego referirse a ellas. Debe asegurarse de que las comillas no colisionen.

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

Al establecer fechas, refiérase a ellas en el código ya que las cadenas pueden entrar en conflicto. Esto no funcionaría con la fecha de inicio establecida anteriormente.

 '${hiveconf:start_date}'

Debemos tener cuidado de no establecer dos comillas simples o dobles para las cadenas cuando se hace referencia a ellas en la consulta.

blondie9x
fuente
2

En caso de que alguien necesite parametrizar la consulta de colmena a través de cli.

Por ejemplo:

hive_query.sql

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

Ahora ejecute el archivo sql anterior desde cli:

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

Prueba este método:

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

funciona bien en mi plataforma.

Typhoonbxq
fuente
0

Puede exportar la variable en el script de shell export CURRENT_DATE = "2012-09-16"

Luego, en hiveql te gusta SELECT * FROM foo WHERE day> = '$ {env: CURRENT_DATE}'

Dileep Dominic
fuente
-7

Puede almacenar la salida de otra consulta en una variable y luego puede usar la misma en su código:

set var=select count(*) from My_table;
${hiveconf:var};
Suman
fuente
Estás equivocado, selecciona count (*) de My_table; se almacenará en var .
Ilya Bystrov