如何在HIVE脚本中设置变量


102

我正在寻找SET varname = valueHive QL中的SQL等效项

我知道我可以做这样的事情:

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

但是然后我得到这个错误:

此处不支持字符“ @”


不幸的是,没有安全的方法来设置字符串变量,因为如果有人在不设置变量的情况下运行查询,那么该字符串将仅使用变量调用作为字符串。:(
combinatorist

Answers:


201

您需要使用特殊的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:USER}的例子。

要查看所有可用变量,请从命令行运行

% hive -e 'set;'

或从配置单元提示符下运行

hive> set;

更新: 我也开始使用hivevar变量,将它们放入hql片段中,我可以使用source命令从hive CLI包含这些片段(或从命令行作为-i选项传递)。这样做的好处是,该变量然后可以与或没有hivevar前缀一起使用,并允许类似于全局使用与局部使用。

因此,假设有一些setup.hql用来设置表名变量:

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中,这可能并不意味着太多,但可以在使用source的文件中包含hql,但可以将某些变量“本地”设置为在脚本的其余部分中使用。


1
这是从命令行传递的参数,我正在Karmasphere中开发查询,并且需要在乞讨中设置一些竞争对象,这样我就不会在脚本中硬编码10次日期。这样有可能吗?
user1678312 2012年

双向工作,如果您愿意set CURRENT_DATE='2012-09-16';,可以稍后使用${hiveconf:CURRENT_DATE}
libjack

1
如果我同时运行多个Hive作业,该如何工作?他们最终会从彼此那里获取价值吗?在自动化中,我通过在其前面加上一些SET语句来构造HQL文件。我想确保如果我同时提交两个使用相同变量名的作业,那么一个作业不会从另一个作业中获取值。您的答案不清楚此处的语义。
MattD 2014年

5
这对我在Hive服务器上有效。但是,我已经在IntelliJ中的本地计算机上设置了一些集成测试。尝试以这种方式使用变量时,我不断收到以下错误消息:FAILED: ParseException line x:y cannot recognize input near '$' '{' 'hiveconf' in expression specification
chepukha

1
@DatabaseCoder据我所知,没有类似的东西会起作用。每当我需要类似的内容时,我都必须先执行查询,然后通过“ --hiveconf”传递
libjack

21

这里的大多数答案都建议使用hiveconfhivevar命名空间来存储变量。所有这些答案都是正确的。但是,还有一个名称空间。

共有三个namespaces可用于保存变量的变量。

  1. hiveconf -hive 从此开始,所有hive配置都存储为该conf的一部分。最初,变量替换不是蜂巢的一部分,当它引入时,所有用户定义的变量也都作为变量的一部分存储。这绝对不是一个好主意。因此,又创建了两个名称空间。
  2. hivevar:存储用户变量
  3. system:存储系统变量。

因此,如果您将变量存储为查询的一部分(例如,日期或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}';

这是我唯一的工作答案。我的ambari配置单元界面中需要引号。
劳伦斯·科彭诺

hivevar和hiveconf有两件事
Rahul Sharma

3

两种简单的方法:

使用配置单元配置

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}'

我们必须注意,在查询中返回字符串时,请不要为字符串设置两次单引号或双引号。


2

万一有人需要通过cli参数配置配置单元查询。

例如:

hive_query.sql

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

现在从cli执行以上sql文件:

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

0

试试这个方法:

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

它在我的平台上运作良好。



-7

您可以将另一个查询的输出存储在变量中,后者可以在代码中使用相同的输出:

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

您错了,请从My_table中选择count(*);将存储在var中
Ilya Bystrov '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.