Как установить переменные в скриптах HIVE

102

Я ищу SQL-эквивалент SET varname = valueв Hive QL

Я знаю, что могу сделать что-то вроде этого:

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

Но потом я получаю такую ​​ошибку:

символ '@' здесь не поддерживается

user1678312
источник
К сожалению, нет безопасного способа установить строковую переменную, потому что, если кто-то выполнит запрос без установки переменной, тогда строка просто будет использовать вызов переменной как строку. :(
комбинатор

Ответы:

202

Вам нужно использовать специальный hiveconf для подстановки переменных. например

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

аналогично вы можете передать командную строку:

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

Обратите внимание, что есть также переменные env и системные , поэтому вы можете ссылаться, ${env:USER}например.

Чтобы увидеть все доступные переменные, из командной строки запустите

% hive -e 'set;'

или из подсказки улья запустите

hive> set;

Обновление: я также начал использовать переменные hivevar , помещая их в фрагменты hql, которые я могу включить из интерфейса sourceкомандной строки hive с помощью команды (или передать как параметр -i из командной строки). Преимущество здесь в том, что переменная может затем использоваться с префиксом hivevar или без него, и разрешать что-то вроде глобального и локального использования.

Итак, предположим, что у вас есть файл setup.hql, который устанавливает переменную tablename:

set hivevar:tablename=mytable;

тогда я могу внести в улей:

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

и использовать в запросе:

hive> select * from ${tablename}

или

hive> select * from ${hivevar:tablename}

Я также мог бы установить "локальное" имя таблицы, что повлияет на использование $ {tablename}, но не $ {hivevar: tablename}

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

против

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

Вероятно, это не слишком много значит для CLI, но может иметь hql в файле, который использует исходный код , но установить некоторые переменные «локально» для использования в остальной части скрипта.

libjack
источник
1
Это передача параметра из командной строки. Я разрабатываю запросы в Karmasphere, и мне нужно установить несколько контентов в начале, чтобы я не кодировал даты 10 раз в моем сценарии. Возможно ли что-то подобное?
user1678312
работает в обоих направлениях, если вы это сделаете, set CURRENT_DATE='2012-09-16';вы можете обратиться к нему позже с помощью${hiveconf:CURRENT_DATE}
libjack
1
Как это работает, если у меня одновременно выполняется несколько заданий Hive? Уберут ли они друг у друга ценности? При автоматизации я создаю файл HQL, добавляя к нему несколько операторов SET. Я хочу быть уверенным, что если я отправляю два задания одновременно с одинаковыми именами переменных, одно задание не будет получать значения из другого задания. Семантика здесь не ясна из вашего ответа.
MattD
5
это работает для меня на сервере Hive. Однако я установил несколько интеграционных тестов на локальном компьютере в IntelliJ. Я продолжаю получать следующую ошибку при попытке использовать переменную таким образом:FAILED: ParseException line x:y cannot recognize input near '$' '{' 'hiveconf' in expression specification
chepukha
1
@DatabaseCoder Насколько мне известно, ничего подобного не работает. Когда мне нужно что-то подобное, я должен выполнить первый запрос, а затем передать его через "--hiveconf"
libjack
21

В большинстве ответов здесь предлагается использовать hiveconfили hivevarпространство имен для хранения переменной. И все эти ответы верны. Однако есть еще одно пространство имен.

Всего namespacesдоступно три переменных для хранения.

  1. hiveconf - улей запущен с этим, вся конфигурация улья сохраняется как часть этого conf. Изначально подстановка переменных не была частью улья, и когда она была введена, все определяемые пользователем переменные также были сохранены как часть этого улья. Что определенно не очень хорошая идея. Так были созданы еще два пространства имен.
  2. hivevar : для хранения пользовательских переменных
  3. система : для хранения системных переменных.

Итак, если вы сохраняете переменную как часть запроса (например, дату или product_number), вы должны использовать hivevarпространство имен, а не hiveconfпространство имен.

Вот как это работает.

hiveconf по-прежнему является пространством имен по умолчанию , поэтому, если вы не предоставите какое-либо пространство имен, он сохранит вашу переменную в пространстве имен hiveconf.

Однако когда дело доходит до ссылки на переменную, это не так. По умолчанию это hivevar пространству имен . Непонятно, правда? Это можно прояснить на следующем примере.

Если вы не предоставите пространство имен, как указано ниже, переменная varбудет храниться в hiveconfпространстве имен.

set var="default_namespace";

Итак, чтобы получить доступ к этому, вам нужно указать hiveconf пространство имен

select ${hiveconf:var};

И если вы не предоставите пространство имен, это выдаст вам ошибку, как указано ниже, причина в том, что по умолчанию, если вы попытаетесь получить доступ к переменной, которая проверяется hivevarтолько в пространстве имен. И в hivevarнем нет переменной с именемvar

select ${var}; 

Мы явно предоставили hivevarпространство имен

set hivevar:var="hivevar_namespace";

поскольку мы предоставляем пространство имен, это будет работать.

select ${hivevar:var}; 

По умолчанию при обращении к переменной используется рабочее пространство hivevar, следующее также будет работать.

select ${var};
Гауранг Шах
источник
7

Вы пробовали использовать знак доллара и скобки следующим образом:

SELECT * 
FROM foo 
WHERE day >= '${CURRENT_DATE}';
ЯБАДАБАДУ
источник
Для меня это единственный рабочий ответ. Кавычки требуются в моем интерфейсе улья амбари.
Laurens Koppenol
есть две вещи, hivevar и hiveconf - обе подробно описаны здесь
Рахул Шарма
3

Два простых способа:

Использование hive conf

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

Использование варов улья

В вашем CLI установите vars, а затем используйте их в улье

set hivevar:USER_NAME='FOO';

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

Документация: https://cwiki.apache.org/confluence/display/Hive/LanguageManual+VariableSubstitution

Савио Д'Суза
источник
2

Одна вещь, о которой следует помнить, - это устанавливать строки, а затем возвращаться к ним. Вы должны убедиться, что цитаты не противоречат друг другу.

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

При установке дат обращайтесь к ним в коде, поскольку строки могут конфликтовать. Это не сработает с установленной выше start_date.

 '${hiveconf:start_date}'

Мы должны помнить о том, чтобы не устанавливать двойные одинарные или двойные кавычки для строк при обратном обращении к ним в запросе.

блондинка9x
источник
2

На всякий случай кому-то нужно параметризовать запрос улья через cli.

Например:

hive_query.sql

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

Теперь выполните указанный выше sql файл из cli:

hive --hivevar CURRENT_DATE="2012-09-16" -f hive_query.sql
Абдул Маннан
источник
0

Попробуйте этот метод:

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

он хорошо работает на моей платформе.

тайфун
источник
0

Вы можете экспортировать переменную в сценарии оболочки export CURRENT_DATE = "2012-09-16"

Тогда в hiveql вам нравится SELECT * FROM foo WHERE day> = '$ {env: CURRENT_DATE}'

Дилип Доминик
источник
-7

Вы можете сохранить вывод другого запроса в переменной, а затем вы можете использовать то же самое в своем коде:

set var=select count(*) from My_table;
${hiveconf:var};
Суман
источник
Вы ошибаетесь, выберите count (*) из My_table; будет храниться в var .
Илья Быстров