【问题标题】:How to set variables in HIVE scripts如何在 HIVE 脚本中设置变量
【发布时间】:2012-09-09 23:40:51
【问题描述】:

我正在 Hive QL 中寻找与 SET varname = value 等效的 SQL

我知道我可以这样做:

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

然后我得到这个错误:

此处不支持字符“@”

【问题讨论】:

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

标签: hive hiveql


【解决方案1】:

您是否尝试过像这样使用美元符号方括号

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

【讨论】:

  • 这对我来说是唯一可行的答案。我的 ambari hive 界面中需要引号。
  • hivevar和hiveconf这两个东西都有详细解释here
【解决方案2】:

您需要使用特殊的 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

请注意,还有 envsystem 变量,因此您可以引用 ${env:USER} 为例。

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

% hive -e 'set;'

或从 hive 提示符运行

hive> set;

更新: 我也开始使用 hivevar 变量,将它们放入 hql sn-ps 我可以使用 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,但可以“本地”设置一些变量以在脚本的其余部分中使用。

【讨论】:

  • 这是从命令行传递一个参数,我正在 Karmasphere 中开发查询,需要在乞求中设置一些内容,这样我就不会在脚本中对日期进行 10 次硬编码。有这样的可能吗?
  • 双向工作,如果你这样做set CURRENT_DATE='2012-09-16';,你可以稍后通过${hiveconf:CURRENT_DATE}参考它
  • 如果我同时运行多个 Hive 作业,这将如何工作?他们最终会从彼此身上汲取价值吗?在自动化中,我通过在 HQL 文件前面加上一些 SET 语句来构建它。我想确保如果我同时提交两个使用相同变量名的作业,一个作业不会从另一个作业中获取值。从您的回答中看不清楚这里的语义。
  • 这适用于我在 Hive 服务器上。但是,我已经在 IntelliJ 的本地机器上设置了一些集成测试。尝试以这种方式使用变量时,我不断收到以下错误:FAILED: ParseException line x:y cannot recognize input near '$' '{' 'hiveconf' in expression specification
  • @DatabaseCoder 据我所知,没有这样的工作。每当我需要类似的东西时,我必须进行第一个查询,然后通过“--hiveconf”
【解决方案3】:

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

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

【讨论】:

  • 你错了,select count(*) from My_table;会存储在var中。
【解决方案4】:

试试这个方法:

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

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

【讨论】:

    【解决方案5】:

    两种简单的方法:

    使用配置单元配置

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

    使用配置单元变量

    在您的 CLI 上设置 vars,然后在 hive 中使用它们

    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

    【讨论】:

      【解决方案6】:

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

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

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

      因此,如果您将变量存储为查询的一部分(即日期或产品编号),您应该使用 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】:

        要注意的一件事是设置字符串,然后再引用它们。您必须确保引号没有冲突。

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

        在设置日期时,在代码中引用它们,因为字符串可能会发生冲突。这不适用于上面设置的 start_date。

         '${hiveconf:start_date}'
        

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

        【讨论】:

          【解决方案8】:

          您可以在 shell 脚本中导出变量 导出 CURRENT_DATE="2012-09-16"

          然后在你喜欢的 hiveql SELECT * FROM foo WHERE day >= '${env:CURRENT_DATE}'

          【讨论】:

            【解决方案9】:

            以防万一有人需要通过 cli 参数化 hive 查询。

            例如:

            hive_query.sql

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

            现在从cli执行上面的sql文件:

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

            【讨论】:

            • 这对我有用,但在 CLI 命令中没有引号。
            【解决方案10】:

            在 Hive 中有多种设置变量的选项。

            如果您希望从 Hive shell 内部设置 Hive 变量,您可以使用 hivevar 设置它。您可以设置字符串或整数数据类型。它们没有问题。

            SET hivevar:which_date=20200808;
            select ${which_date};
            

            如果您打算从 shell 脚本设置变量并希望将这些变量传递到您的 Hive 脚本 (HQL) 文件中,您可以在调用 hive 或 beeline 命令时使用--hivevar 选项。

            # shell script will invoke script like this
            beeline --hivevar tablename=testtable -f select.hql
            
            -- select.hql file
            select * from <dbname>.${tablename};
            

            【讨论】:

              猜你喜欢
              • 2017-09-24
              • 1970-01-01
              • 2011-11-26
              • 2016-10-03
              • 1970-01-01
              • 1970-01-01
              • 2012-01-12
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多