วิธีตั้งค่าตัวแปรในสคริปต์ HIVE


102

ฉันกำลังมองหา SQL ที่เทียบเท่าSET varname = valueใน Hive QL

ฉันรู้ว่าฉันสามารถทำสิ่งนี้ได้:

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

แต่แล้วฉันก็ได้รับข้อผิดพลาดนี้:

ที่นี่ไม่รองรับอักขระ "@"


น่าเสียดายที่ไม่มีวิธีที่ปลอดภัยในการตั้งค่าตัวแปรสตริงเนื่องจากหากมีคนเรียกใช้แบบสอบถามโดยไม่ตั้งค่าตัวแปรสตริงก็จะใช้การเรียกตัวแปรเป็นสตริง :(
combinatorist

คำตอบ:


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 snippets ที่ฉันสามารถรวมจาก hive CLI โดยใช้sourceคำสั่ง (หรือผ่านตัวเลือก -i จากบรรทัดคำสั่ง) ข้อดีคือจากนั้นตัวแปรสามารถใช้โดยมีหรือไม่มีคำนำหน้า hivevar และอนุญาตบางอย่างที่คล้ายกับการใช้งานทั่วโลกเทียบกับท้องถิ่น

ดังนั้นสมมติว่ามีsetup.hqlซึ่งตั้งค่าตัวแปร tablename:

set hivevar:tablename=mytable;

จากนั้นฉันสามารถนำเข้าสู่รัง:

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

และใช้ในการสืบค้น:

hive> select * from ${tablename}

หรือ

hive> select * from ${hivevar:tablename}

ฉันยังสามารถตั้งชื่อตาราง "local" ซึ่งจะส่งผลต่อการใช้ $ {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 ในไฟล์ที่ใช้ซอร์สได้ แต่ตั้งค่าตัวแปรบางตัว "ในเครื่อง" เพื่อใช้ในส่วนที่เหลือของสคริปต์


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 - กลุ่มเริ่มต้นด้วยสิ่งนี้การกำหนดค่ารังทั้งหมดจะถูกเก็บไว้เป็นส่วนหนึ่งของการกำหนดค่านี้ ในขั้นต้นการแทนที่ตัวแปรไม่ได้เป็นส่วนหนึ่งของรังและเมื่อได้รับการแนะนำตัวแปรที่ผู้ใช้กำหนดเองทั้งหมดจะถูกเก็บไว้เป็นส่วนหนึ่งของสิ่งนี้เช่นกัน ซึ่งไม่ใช่ความคิดที่ดีแน่นอน จึงมีการสร้างเนมสเปซเพิ่มขึ้นอีกสองแห่ง
  2. hivevar : เพื่อเก็บตัวแปรของผู้ใช้
  3. ระบบ : เพื่อจัดเก็บตัวแปรระบบ

ดังนั้นหากคุณจัดเก็บตัวแปรเป็นส่วนหนึ่งของแบบสอบถาม (เช่นวันที่หรือหมายเลขผลิตภัณฑ์) คุณควรใช้hivevarเนมสเปซไม่ใช่hiveconfเนมสเปซ

และนี่คือวิธีการทำงาน

hiveconfยังคงเป็นเนมสเปซเริ่มต้นดังนั้นหากคุณไม่ระบุเนมสเปซใด ๆ ระบบจะเก็บตัวแปรของคุณไว้ในเนมสเปซของ hiveconf

อย่างไรก็ตามเมื่อพูดถึงตัวแปรนั้นไม่เป็นความจริง โดยค่าเริ่มต้นหมายถึงเนมสเปซแบบไฮเววาร์ สับสนใช่มั้ย? จะชัดเจนขึ้นด้วยตัวอย่างต่อไปนี้

หากคุณไม่ได้ระบุเนมสเปซตามที่ระบุไว้ด้านล่างตัวแปร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 ของฉัน
Laurens Koppenol

มีสองสิ่งที่ hivevar และ hiveconf - ทั้งสองอย่างมีรายละเอียดอธิบายไว้ที่นี่
Rahul Sharma

3

สองวิธีง่ายๆ:

ใช้ hive conf

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

การใช้ hive vars

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

ตอนนี้เรียกใช้ไฟล์ sql ด้านบนจาก cli:

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


0

คุณสามารถส่งออกตัวแปรในการส่งออกเชลล์สคริปต์ 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 .
Ilya Bystrov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.