Reputation: 117
I am trying to dynamically union all tables in a specific BigQuery dataset where the table names have the suffix "client". Due to the use of customer encryption keys, I cannot utilize wildcards, so I am using a FOR loop to build the query.
Here is the BigQuery script I am using:
DECLARE query STRING DEFAULT '';
DECLARE table_names ARRAY<STRING>;
SET table_names = (
SELECT ARRAY_AGG(table_name) AS table_names
FROM `project.dataset.INFORMATION_SCHEMA.TABLES`
WHERE table_name LIKE '%client'
);
FOR table_name IN (SELECT * FROM UNNEST(table_names)) DO
SET query = IF(
query = '',
CONCAT('SELECT * FROM `project.dataset.', table_name, '`'),
CONCAT(query, ' UNION ALL SELECT * FROM `project.dataset.', table_name, '`')
);
END FOR;
EXECUTE IMMEDIATE query;
However, I am encountering the following error:
Query error: No matching signature for function CONCAT for argument types: STRING, STRUCT<f0_ STRING>, STRING. Supported signatures: CONCAT(STRING, [STRING, ...]); CONCAT(BYTES, [BYTES, ...]) at [13:5]
It seems that the CONCAT function is having trouble with the types of arguments provided, particularly with the table_name.
Could someone help me understand why this error is occurring and suggest a solution to correctly build and execute the dynamic query?
Your help is much appreciated!
Upvotes: 0
Views: 53
Reputation: 173161
Meantime, below is the fix for your script in case if you need to run it this way:
DECLARE query STRING DEFAULT '';
DECLARE table_names ARRAY<STRING>;
SET table_names = (
SELECT ARRAY_AGG(table_name) AS table_names
FROM `project.dataset.INFORMATION_SCHEMA.TABLES`
# WHERE table_name LIKE '%client'
);
FOR record IN (SELECT table_name FROM UNNEST(table_names) table_name) DO
SET query = IF(
query = '',
CONCAT('SELECT * FROM `project.dataset.', record.table_name, '`'),
CONCAT(query, ' UNION ALL SELECT * FROM `project.dataset.', record.table_name, '`')
);
END FOR;
EXECUTE IMMEDIATE query;
I think it is self descriptive. Most important to accept the fact that you are looping through records and each record is a struct. so if you need to reference specific field in that record you need to use record.column_name
Upvotes: 1
Reputation: 173161
It is never good idea to use cursor when you can do set based operation
Try below instead
DECLARE query STRING DEFAULT '';
SET query = (
SELECT STRING_AGG(CONCAT('SELECT * FROM `project.dataset.', table_name, '`'), ' UNION ALL ')
FROM `project.dataset.INFORMATION_SCHEMA.TABLES`
WHERE table_name LIKE '%client'
);
EXECUTE IMMEDIATE query;
or just simply
EXECUTE IMMEDIATE (
SELECT STRING_AGG(CONCAT('SELECT * FROM `project.dataset.', table_name, '`'), ' UNION ALL ')
FROM `project.dataset.INFORMATION_SCHEMA.TABLES`
WHERE table_name LIKE '%client'
);
Upvotes: 1