Como definir variáveis ​​em scripts HIVE

102

Estou procurando o equivalente SET varname = valueem SQL no Hive QL

Eu sei que posso fazer algo assim:

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

Mas então recebo este erro:

caractere '@' não suportado aqui

user1678312
fonte
Infelizmente, não há uma maneira segura de definir uma variável de string porque se alguém executar a consulta sem definir a variável, a string simplesmente usará a chamada de variável como uma string. :(
combinatorist

Respostas:

201

Você precisa usar o hiveconf especial para substituição de variável. por exemplo

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

da mesma forma, você pode passar a linha de comando:

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

Observe que também existem variáveis env e sistema , portanto, você pode fazer referência, ${env:USER}por exemplo.

Para ver todas as variáveis ​​disponíveis, na linha de comando, execute

% hive -e 'set;'

ou a partir do prompt do hive, execute

hive> set;

Atualização: comecei a usar variáveis hivevar também, colocando-as em fragmentos hql que posso incluir da CLI do hive usando o sourcecomando (ou passar como a opção -i da linha de comando). O benefício aqui é que a variável pode então ser usada com ou sem o prefixo hivevar e permitir algo semelhante ao uso global versus local.

Portanto, suponha que haja algum setup.hql que defina uma variável tablename:

set hivevar:tablename=mytable;

então, posso trazer para a colmeia:

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

e usar na consulta:

hive> select * from ${tablename}

ou

hive> select * from ${hivevar:tablename}

Eu também poderia definir um tablename "local", o que afetaria o uso de $ {tablename}, mas não de $ {hivevar: tablename}

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

vs

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

Provavelmente não significa muito da CLI, mas pode ter hql em um arquivo que usa o código-fonte , mas defina algumas das variáveis ​​"localmente" para usar no restante do script.

libjack
fonte
1
Isso é passar um parâmetro da linha de comando que estou desenvolvendo consultas no Karmasphere e preciso definir alguns contants no início para que eu não fixe datas 10 vezes em meu script. É possível algo assim?
user1678312
funciona nos dois sentidos, se você fizer set CURRENT_DATE='2012-09-16';isso, poderá consultá-lo mais tarde com${hiveconf:CURRENT_DATE}
libjack
1
Como isso funciona se eu tiver vários trabalhos do Hive em execução simultaneamente? Eles vão acabar pegando valores uns dos outros? Na automação, estou construindo um arquivo HQL acrescentando algumas instruções SET. Quero ter certeza de que, se enviar dois trabalhos ao mesmo tempo que usam os mesmos nomes de variáveis, um não coletará os valores do outro. A semântica aqui não está clara em sua resposta.
MattD
5
isso funciona para mim no servidor Hive. No entanto, configurei alguns testes de integração na máquina local no IntelliJ. Eu continuo recebendo o seguinte erro ao tentar usar a variável desta forma:FAILED: ParseException line x:y cannot recognize input near '$' '{' 'hiveconf' in expression specification
chepukha
1
@DatabaseCoder Até onde sei, nada disso funcionará. Sempre que preciso de algo assim, tenho que fazer a primeira consulta e, em seguida, passar via "--hiveconf"
libjack
21

A maioria das respostas aqui sugeriu usar hiveconfou hivevarnamespace para armazenar a variável. E todas essas respostas estão certas. No entanto, há mais um namespace.

Há um total de três namespacesdisponíveis para variáveis ​​de retenção.

  1. hiveconf - hive começou com isso, toda a configuração do hive é armazenada como parte deste conf. Inicialmente, a substituição de variável não fazia parte do hive e, quando foi introduzida, todas as variáveis ​​definidas pelo usuário também foram armazenadas como parte dela. O que definitivamente não é uma boa ideia. Portanto, mais dois namespaces foram criados.
  2. hivevar : para armazenar variáveis ​​de usuário
  3. sistema : Para armazenar variáveis ​​de sistema.

Portanto, se você estiver armazenando uma variável como parte de uma consulta (ou seja, data ou número do produto), você deve usar o hivevarnamespace e não o hiveconfnamespace.

E é assim que funciona.

hiveconf ainda é o namespace padrão , portanto, se você não fornecer nenhum namespace, ele armazenará sua variável no namespace hiveconf.

No entanto, quando se trata de se referir a uma variável, isso não é verdade. Por padrão, ele se refere ao namespace hivevar . Confuso, certo? Isso pode ficar mais claro com o exemplo a seguir.

Se você não fornecer o namespace conforme mencionado abaixo, a variável varserá armazenada no hiveconfnamespace.

set var="default_namespace";

Então, para acessar isso, você precisa especificar o hiveconf namespace

select ${hiveconf:var};

E se você não fornecer o namespace , ocorrerá um erro conforme mencionado abaixo, o motivo é que, por padrão, se você tentar acessar uma variável, ele verifica hivevarapenas no namespace. E hivevarnão há nenhuma variável chamadavar

select ${var}; 

Fornecemos um hivevarnamespace explicitamente

set hivevar:var="hivevar_namespace";

como estamos fornecendo o namespace, isso funcionará.

select ${hivevar:var}; 

E como padrão, a área de trabalho usada durante a referência de uma variável é hivevar, o seguinte também funcionará.

select ${var};
Gaurang Shah
fonte
7

Você já tentou usar o cifrão e colchetes como este:

SELECT * 
FROM foo 
WHERE day >= '${CURRENT_DATE}';
YABADABADOU
fonte
Esta é a única resposta que funciona para mim. As aspas são necessárias na minha interface ambari hive.
Laurens Koppenol
há duas coisas hivevar e hiveconf- ambas são explicadas em detalhes aqui
Rahul Sharma
3

Duas maneiras fáceis:

Usando Hive conf

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

Usando hive vars

Em seu CLI, defina vars e use-os no hive

set hivevar:USER_NAME='FOO';

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

Documentação: https://cwiki.apache.org/confluence/display/Hive/LanguageManual+VariableSubstitution

Savio D'Souza
fonte
2

Uma coisa a se ter em mente é definir strings e, em seguida, consultar de volta a eles. Você tem que ter certeza de que as aspas não estão colidindo.

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

Ao definir datas, em seguida, referindo-se a elas no código, pois as strings podem entrar em conflito. Isso não funcionaria com start_date definido acima.

 '${hiveconf:start_date}'

Devemos estar atentos para não definir duas aspas simples ou duplas para strings ao fazer referência a elas na consulta.

blondie9x
fonte
2

Caso alguém precise parametrizar a consulta do hive via CLI.

Por exemplo:

hive_query.sql

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

Agora execute o arquivo sql acima em cli:

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

Experimente este método:

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

funciona bem na minha plataforma.

Typhoonbxq
fonte
0

Você pode exportar a variável no script de shell export CURRENT_DATE = "2012-09-16"

Então, no hiveql, você gosta de SELECT * FROM foo WHERE day> = '$ {env: CURRENT_DATE}'

Dileep Dominic
fonte
-7

Você pode armazenar a saída de outra consulta em uma variável e, posteriormente, pode usar a mesma em seu código:

set var=select count(*) from My_table;
${hiveconf:var};
Suman
fonte
Você está errado, selecione count (*) em My_table; será armazenado em var .
Ilya Bystrov,