我有一个数据集,其中有几百个表,我想删除其中的大部分。我不想编写数百个 DROP TABLE 语句,因此我希望可以使用动态 SQL。我试过这个:
FOR record IN (
select dataset_id,table_id
from mydataset.__TABLES__
where <some-criteria-to-get-the-tables-I-want-to-drop>
)
DO
execute immediate "drop table `?`.`?`" USING record.dataset_id, record.table_id;
END FOR;
但是失败并出现错误
无效值:无效的数据集 ID“?”。数据集 ID 必须是字母数字(加上下划线和破折号),并且长度不得超过 1024 个字符。在 [1:1]
有人可以告诉我如何使用动态 SQL 删除表吗?更好的是,如果有人知道删除大量桌子的更好方法,请告诉我。
如果您使用表名作为参数,您将收到如下错误。
无效的 EXECUTE IMMEDIATE sql 字符串
,查询参数不能用于代替表名,位于 [4:19]SELECT * FROM ?.?
所以,我通常做的是使用 FORMAT() 函数来生成动态查询。
FOR t IN (SELECT dataset_id, table_id FROM testset.__TABLES__)
DO
EXECUTE IMMEDIATE FORMAT("""
DROP TABLE `%s`.`%s`;
""", t.dataset_id, t.table_id);
END FOR;
有兴趣知道为什么使用 BQ 动态 SQL 不起作用。
下面将起作用并在查询中引用?是一个公正的字符串。
EXECUTE IMMEDIATE "SELECT '?', ?, ?" USING 'dataset', 'table';
+-----+-----+---------+-------+
| Row | f0_ | f1_ | f2_ |
+-----+-----+---------+-------+
| 1 | ? | dataset | table |
+-----+-----+---------+-------+
如果用反引号引用 ?,反引号内的字符串将被视为 标识符(即列名或变量),并且不会被位置参数替换,但标识符 ? 没有意义。
EXECUTE IMMEDIATE "SELECT `?`, `?`" USING 'dataset', 'table';
没有反引号,下面的 ? 被替换为参数。但会因错误而失败。
EXECUTE IMMEDIATE "SELECT * FROM ?.?" USING 'dataset', 'table';
无效的 EXECUTE IMMEDIATE sql 字符串
,查询参数不能用于代替 [1:19] 处的表名SELECT * FROM ?.?
我有如下动态 SQL 的解决方案。 希望对你有帮助
/* DROP Sharded tables */
DECLARE start_date DATE default '2023-01-02'; -- update to yours.
DECLARE end_date DATE default '2024-01-02'; -- update to yours.
DECLARE table_date STRING;
SET table_date = FORMAT_DATE('%Y%m%d', start_date); -- YYYYMMDD
LOOP
IF start_date > end_date THEN
BREAK;
END IF;
EXECUTE IMMEDIATE FORMAT(
"""
DROP TABLE `dateset.table_name_%s`; -- update to yours.
"""
,table_date
);
SET start_date = DATE_ADD(start_date , INTERVAL 1 DAY);
SET table_date = FORMAT_DATE('%Y%m%d', start_date);
END LOOP;