18、Snowflake 数据编程:脚本与 Snowpark 全解析

Snowflake 数据编程:脚本与 Snowpark 全解析

1. 安全数据共享与主键生成

在数据处理中,使用序列生成表的主键是常见操作。但如同安全视图一样,如果这些主键对没有访问所有底层数据权限的用户可见,他们可能会猜出数据分布。因此,应隐藏或不将序列生成的列作为函数输出,就像在安全视图中不显示它一样。

2. Snowflake 脚本概述

Snowflake 不仅支持使用 SQL 查询数据,还支持以编写过程代码块、创建存储过程和函数以及创建 API 调用的形式对数据进行编程操作。Snowflake 脚本允许在 SQL 语句不足以满足需求时编写过程逻辑,可用于编写存储过程、函数和过程代码块。

2.1 Snowflake 脚本块结构

Snowflake 脚本块由关键字分隔的部分组成,如下所示:

DECLARE
  -- (变量、游标、异常、结果集)
BEGIN
  -- (Snowflake 脚本和 SQL 语句)
EXCEPTION
  -- (处理异常的语句)
END;

各部分作用如下:
- DECLARE :可声明将使用的变量、游标、异常或结果集,此部分可选。
- BEGIN … END :在 BEGIN 和 END 关键字之间编写 SQL 语句和其他 Snowflake 脚本结构。
- EXCEPTION :可编写异常处理代码,用于捕获异常,此部分可选。

最基本的 Snowflake 脚本块只需 BEGIN 和 END 关键字。例如,创建两个表 FRUIT 和 FRUIT_INVENTORY 的代码块:

BEGIN
  create table FRUIT (
    fruit_id number,
    name varchar,
    color varchar
  );
  create table FRUIT_INVENTORY (
    fruit_id number,
    inv_date date,
    amount_kg number
  );
END;

执行此块代码时,可像在 Snowsight 中执行任何 SQL 查询一样,使用所选的数据库、模式和虚拟仓库。若使用 Classic UI,需参考 Snowflake 文档了解代码格式和执行方法。

上述代码块为匿名块,可独立执行且无名称。也可在存储过程中使用块,例如:

create procedure CREATE_SAMPLE_TABLES()
  returns number
  language sql
  as
BEGIN
  create or replace table FRUIT (
    fruit_id number,
    name varchar,
    color varchar
  );
  create or replace table FRUIT_INVENTORY (
    fruit_id number,
    inv_date date,
    amount_kg number
  );
END;

执行存储过程使用 CALL 语句:

call CREATE_SAMPLE_TABLES();

2.2 变量声明

在 Snowflake 脚本中,可声明变量并定义其数据类型。变量可用于表达式、SQL 语句或作为 Snowflake 脚本结构的一部分。可通过指定确切数据类型显式定义变量的数据类型,也可提供初始值,Snowflake 将根据提供的值确定数据类型。

在块的 DECLARE 部分声明变量的语法如下:
- <variable_name> <data_type>;
- <variable_name> DEFAULT <expression>;
- <variable_name> <data_type> DEFAULT <expression>;

数据类型可以是:
- SQL 数据类型
- CURSOR
- RESULTSET
- EXCEPTION

例如,在 DECLARE 部分声明变量的代码块:

DECLARE
  weight_lb number;
  weight_kg number;
BEGIN
  weight_lb := 145;
  weight_kg := 0.453592 * weight_lb;
  return weight_kg;
END;

此例声明了两个变量 WEIGHT_LB 和 WEIGHT_KG,将 145 赋值给 WEIGHT_LB,用其进行计算并将结果赋值给 WEIGHT_KG,最后返回 WEIGHT_KG 的值。块内声明的变量不能在块外使用。

也可在 BEGIN 和 END 关键字之间使用 LET 命令声明变量,例如:

DECLARE
    weight_kg number;
BEGIN
    let weight_lb := 145;
    weight_kg := 0.453592 * weight_lb;
    return weight_kg;
END;

当不明确指定数据类型声明变量时,Snowflake 脚本会从赋值表达式推断数据类型。为避免歧义,建议明确定义数据类型。

2.3 变量赋值

使用 := 运算符为变量赋值,语法为:

<variable_name> := <expression>;

变量也可用于 SQL 语句,此时需在变量名前加冒号。例如,将 WEIGHT_KG 变量的值插入表中:

insert into FRUIT_INVENTORY (amount_kg) values (:weight_kg);

变量还可作为对象名称,如表名,此时需用 IDENTIFIER 关键字括起来。例如,从 TABLE_NAME 变量存储的表中选择数据:

select sum(amount_kg) from identifier(:table_name);

若在表达式或使用 RETURN 等 Snowflake 脚本语言元素时使用变量,无需在变量前加冒号。例如,返回 WEIGHT_KG 变量的值:

return weight_kg;

当代码块用于存储过程时,可使用作为参数传递给过程的变量。例如,创建基于重量转换的存储过程:

create procedure CONVERT_WEIGHT(weight_lb number)
  returns number
  language sql
  as
DECLARE
  weight_kg number;
BEGIN
  weight_kg := 0.453592 * weight_lb;
  return weight_kg;
END;

由于 WEIGHT_LB 变量作为存储过程的参数,无需在代码块中声明。使用时无需冒号前缀。执行存储过程时,使用 CALL 语句并提供输入参数的值:

call CONVERT_WEIGHT(145);

2.4 分支和循环

Snowflake 脚本提供各种分支和循环语句,包括 IF 和 CASE 语句用于分支,以及 FOR、WHILE、REPEAT 和 LOOP 语句用于过程逻辑中的循环。

2.4.1 IF 语句示例
BEGIN
  let weight_lb := 114;
  IF (weight_lb < 100) THEN
    return 'less than 100';
  ELSEIF (weight_lb = 100) THEN
    return 'exactly 100';
  ELSE
    return 'more than 100';
  END IF;
END;

IF 语句的行为与许多编程语言中的 IF 结构类似,IF 关键字后的表达式必须包含在括号中。

2.4.2 CASE 语句示例
BEGIN
  let fruit_name := 'banana';
  CASE (fruit_name)
    WHEN 'apple' THEN
      return 'red';
    WHEN 'banana' THEN
      return 'yellow';
    WHEN 'avocado' THEN
      return 'green';
    ELSE
      return 'unknown';
  END;
END;

CASE 语句类似于 IF 语句,但可有多个条件。Snowflake 会执行第一个值与表达式匹配的 WHEN 子句。

2.4.3 FOR 循环示例

基于计数器的 FOR 循环执行五次:

DECLARE
  counter integer default 0;
  maximum_count integer default 5;
BEGIN
  FOR i in 1 to maximum_count do
    counter := counter + 1;
  END FOR;
  return counter;
END;

在循环结构中,可使用 BREAK 命令提前终止循环,使用 CONTINUE 命令跳过当前迭代的剩余语句并继续下一次迭代。

2.5 游标使用

在 Snowflake 脚本块中,可使用 INTO 子句将 SELECT 语句返回的值赋给变量。例如:

DECLARE
  v_id integer;
  v_name varchar;
  v_color varchar;
BEGIN
  select fruit_id, name, color
    into v_id, v_name, v_color
    from FRUIT
    where fruit_id = 1;
END;

此语法仅在 SELECT 语句返回单行时有效,因此查询中有过滤单个 FRUIT_ID 的 WHERE 条件。

当要处理 SELECT 语句返回的多行数据时,可使用游标逐行迭代查询结果。使用游标步骤如下:
1. 在块的 DECLARE 部分声明游标,提供游标将执行的查询。
2. 在代码块的主要部分(BEGIN 和 END 关键字之间),执行 OPEN 命令打开游标、执行查询并将结果加载到游标中,然后执行 FETCH 命令逐行获取并使用循环命令处理,处理完后执行 CLOSE 命令关闭游标。
3. 或者,在代码块的主要部分使用基于游标的 FOR 循环迭代结果集,使用时无需显式打开和关闭游标。

例如,使用之前创建的 FRUIT 和 FRUIT_INVENTORY 表插入数据:

insert into FRUIT values
  (1, 'apple', 'red'),
  (2, 'banana', 'yellow'),
  (3, 'avocado', 'green');
insert into FRUIT_INVENTORY values
  (1, sysdate(), 110),
  (2, sysdate(), 80),
  (3, sysdate(), 145);

声明游标并使用基于游标的 FOR 循环处理:

DECLARE
  c1 cursor for
    select amount_kg from FRUIT_INVENTORY;
  total_amount number default 0;
BEGIN
  FOR record in c1 do
    total_amount := total_amount + record.amount_kg;
  END FOR;
  return total_amount;
END;

也可使用 RESULTSET_FROM_CURSOR 函数和 TABLE 关键字从游标返回表:

DECLARE
  c2 cursor for
    select FRUIT.name, FRUIT_INVENTORY.amount_kg
    from FRUIT_INVENTORY
    inner join FRUIT
      on FRUIT.fruit_id = FRUIT_INVENTORY.fruit_id;
BEGIN
  open c2;
  return TABLE(resultset_from_cursor(c2));
END;

2.6 受影响的行数和查询 ID

每次执行 DML 命令后,Snowflake 脚本会设置以下全局变量:
- SQLROWCOUNT :最后一个 DML 语句影响的行数。
- SQLFOUND :若最后一个 DML 语句影响了一行或多行,则为 TRUE。
- SQLNOTFOUND :若最后一个 DML 语句未影响任何行,则为 TRUE。

例如,更新 FRUIT_INVENTORY 表中的记录并返回 SQLROWCOUNT 的值:

BEGIN
  update FRUIT_INVENTORY
    set amount_kg = 175 where fruit_id = '2';
  return SQLROWCOUNT;
END;

此例中,一行被更新,返回值为 1。同样,也可返回 SQLFOUND 变量的值,应为 TRUE。

另一个有用的全局变量是 SQLID,它包含最后执行的查询的 ID。例如:

BEGIN
  update FRUIT_INVENTORY
    set amount_kg = 150 where fruit_id = '3';
  return SQLID;
END;

此例从代码块返回 UPDATE 语句的查询 ID。

2.7 异常处理

与许多编程语言类似,Snowflake 脚本允许在脚本块中引发异常。异常可能由多种原因引起,如数据库错误、脚本代码语法错误、数据类型转换错误等。

由于 Snowflake 脚本块可以嵌套,异常处理程序也可以嵌套。当在脚本块中引发异常时,Snowflake 按以下优先级查找异常处理程序:
1. 若发生异常的块有自己的异常处理程序来捕获异常,则执行该处理程序。
2. 若该块没有自己的异常处理程序,则执行包含当前块的块中的异常处理程序。
3. 异常处理嵌套继续,遵循脚本块的嵌套层次结构。每次发生错误时,若当前块中没有异常处理程序,异常将向外传递一层,直到找到合适的异常处理程序或到达最外层。

使用 EXCEPTION 子句编写异常处理程序,可使用 WHEN 子句处理单个异常。Snowflake 脚本中一些常见的内置异常包括:
- STATEMENT_ERROR :执行语句时出错引发。
- EXPRESSION_ERROR :与表达式相关的错误引发,如尝试将表达式的值赋给不兼容数据类型的变量。

每个异常返回的几个变量提供了有关内置异常的额外信息:
- SQLCODE :表示错误代码的整数。
- SQLERRM :包含错误消息的字符串。
- SQLSTATE :基于 ANSI SQL 标准的代码。

使用 OTHER 关键字处理未命名的其他异常。例如,尝试从 FRUIT 表中选择多行并将结果存储在变量中,此语句会失败,可在添加的 EXCEPTION 部分捕获异常:

DECLARE
  v_name varchar;
BEGIN
  select name
  into v_name
  from FRUIT;
  return v_name;
EXCEPTION
  WHEN statement_error THEN
    return object_construct('Error type', 'Statement error',
      'SQLCODE', sqlcode, 'SQLERRM', sqlerrm,
      'SQLSTATE', sqlstate);
  WHEN expression_error THEN
    return object_construct('Error type', 'Expression error',
      'SQLCODE', sqlcode, 'SQLERRM', sqlerrm,
      'SQLSTATE', sqlstate);
  WHEN other THEN
    return object_construct('Error type', 'Other error',
      'SQLCODE', sqlcode, 'SQLERRM', sqlerrm,
      'SQLSTATE', sqlstate);
END;

以下是一个 mermaid 格式的流程图,展示了 Snowflake 脚本块的基本结构:

graph TD;
    A[开始] --> B{DECLARE部分};
    B -- 可选 --> C[声明变量、游标等];
    B -- 无 --> D[BEGIN部分];
    C --> D;
    D --> E[编写SQL和脚本语句];
    E --> F{EXCEPTION部分};
    F -- 可选 --> G[编写异常处理代码];
    F -- 无 --> H[END部分];
    G --> H;
    H --> I[结束];

通过以上内容,我们详细了解了 Snowflake 脚本的各个方面,包括脚本块结构、变量声明与赋值、分支和循环、游标使用、全局变量以及异常处理等。这些功能为在 Snowflake 中进行数据编程提供了强大的支持。

3. 总结与操作要点回顾

3.1 关键知识点总结

知识点 描述
安全数据共享 注意主键生成序列的可见性,避免无权限用户猜测数据分布,可隐藏或不将其作为函数输出。
Snowflake 脚本块 由 DECLARE、BEGIN … END、EXCEPTION 部分组成,最基本只需 BEGIN 和 END。可用于创建匿名块或存储过程。
变量声明 可在 DECLARE 部分或 BEGIN 和 END 之间使用 LET 命令声明,可显式或隐式定义数据类型,建议显式定义避免歧义。
变量赋值 使用 := 运算符,在 SQL 语句中使用变量需加冒号,作为对象名时用 IDENTIFIER 关键字。
分支和循环 提供 IF、CASE 语句用于分支,FOR、WHILE、REPEAT 和 LOOP 语句用于循环,IF 后表达式需括号。
游标使用 处理多行数据时,可在 DECLARE 部分声明,在 BEGIN 和 END 之间操作,也可用基于游标的 FOR 循环。
全局变量 SQLROWCOUNT 记录 DML 影响行数,SQLFOUND 和 SQLNOTFOUND 反映是否有行受影响,SQLID 记录最后查询 ID。
异常处理 可嵌套,使用 EXCEPTION 子句和 WHEN 子句处理,有内置异常和自定义异常,用 OTHER 处理未命名异常。

3.2 操作步骤梳理

3.2.1 创建存储过程
  1. 定义存储过程名称、返回类型和语言。
  2. as 关键字后编写脚本块,可包含变量声明、SQL 语句等。
  3. 使用 CALL 语句执行存储过程并提供参数(如有)。

示例代码:

create procedure CONVERT_WEIGHT(weight_lb number)
  returns number
  language sql
  as
DECLARE
  weight_kg number;
BEGIN
  weight_kg := 0.453592 * weight_lb;
  return weight_kg;
END;

call CONVERT_WEIGHT(145);
3.2.2 使用游标处理多行数据
  1. 在 DECLARE 部分声明游标,指定查询语句。
  2. 在 BEGIN 和 END 之间,可选择使用 OPEN、FETCH、CLOSE 命令操作,或使用基于游标的 FOR 循环。

示例代码:

DECLARE
  c1 cursor for
    select amount_kg from FRUIT_INVENTORY;
  total_amount number default 0;
BEGIN
  FOR record in c1 do
    total_amount := total_amount + record.amount_kg;
  END FOR;
  return total_amount;
END;
3.2.3 异常处理
  1. 在脚本块中添加 EXCEPTION 部分。
  2. 使用 WHEN 子句处理不同类型的异常,可使用内置异常或自定义异常。
  3. 用 OTHER 关键字处理未命名的异常。

示例代码:

DECLARE
  v_name varchar;
BEGIN
  select name
  into v_name
  from FRUIT;
  return v_name;
EXCEPTION
  WHEN statement_error THEN
    return object_construct('Error type', 'Statement error',
      'SQLCODE', sqlcode, 'SQLERRM', sqlerrm,
      'SQLSTATE', sqlstate);
  WHEN expression_error THEN
    return object_construct('Error type', 'Expression error',
      'SQLCODE', sqlcode, 'SQLERRM', sqlerrm,
      'SQLSTATE', sqlstate);
  WHEN other THEN
    return object_construct('Error type', 'Other error',
      'SQLCODE', sqlcode, 'SQLERRM', sqlerrm,
      'SQLSTATE', sqlstate);
END;

3.3 操作流程可视化

以下是一个 mermaid 格式的流程图,展示了使用 Snowflake 脚本进行数据处理的一般流程:

graph LR;
    A[开始] --> B[定义需求];
    B --> C{是否需要存储过程};
    C -- 是 --> D[创建存储过程];
    C -- 否 --> E[编写脚本块];
    D --> F[声明变量和游标];
    E --> F;
    F --> G[编写 SQL 语句和逻辑];
    G --> H{是否需要异常处理};
    H -- 是 --> I[添加 EXCEPTION 部分];
    H -- 否 --> J[执行脚本];
    I --> J;
    J --> K{是否使用游标};
    K -- 是 --> L[操作游标];
    K -- 否 --> M[完成操作];
    L --> M;
    M --> N[结束];

通过上述总结和梳理,我们对 Snowflake 脚本和 Snowpark 的相关知识有了更清晰的认识,能够更熟练地运用这些技术进行数据编程和处理。无论是处理简单的数据查询,还是构建复杂的存储过程和异常处理机制,都可以依据这些操作要点和流程来实现。希望这些内容能帮助你在实际应用中更好地发挥 Snowflake 的强大功能。

内容概要:本文为《科技类企业品牌传播白皮书》,系统阐述了新闻媒体发稿、自媒体博主种草短视频矩阵覆盖三大核心传播策略,并结合“传声港”平台的AI工具资源整合能力,提出适配科技企业的品牌传播解决方案。文章深入分析科技企业传播的特殊性,包括受众圈层化、技术复杂性传播通俗性的矛盾、产品生命周期影响及2024-2025年传播新趋势,强调从“技术输出”向“价值引领”的战略升级。针对三种传播方式,分别从适用场景、操作流程、效果评估、成本效益、风险防控等方面提供详尽指南,并通过平台AI能力实现资源智能匹配、内容精准投放链路效果追踪,最终构建“信任—种草—曝光”三位一体的传播闭环。; 适合人群:科技类企业品牌市场负责人、公关传播从业者、数字营销管理者及初创科技公司创始人;具备一定品牌传播基础,关注效果可量化AI工具赋能的专业人士。; 使用场景及目标:①制定科技产品生命周期的品牌传播策略;②优化媒体发稿、KOL合作短视频运营的资源配置ROI;③借助AI平台实现传播内容的精准触达、效果监测风险控制;④提升品牌在技术可信度、用户信任市场影响力方面的综合竞争力。; 阅读建议:建议结合传声港平台的实际工具模块(如AI选媒、达人匹配、数据驾驶舱)进行对照阅读,重点关注各阶段的标准化流程数据指标基准,将理论策略平台实操深度融合,推动品牌传播从经验驱动转向数据工具双驱动。
【3D应力敏感度分析拓扑优化】【基于p-范数局应力衡量的3D敏感度分析】基于伴随方法的有限元分析和p-范数应力敏感度分析(Matlab代码实现)内容概要:本文档围绕“基于p-范数局应力衡量的3D应力敏感度分析”展开,介绍了一种结合伴随方法有限元分析的拓扑优化技术,重点实现了3D结构在应力约束下的敏感度分析。文中详细阐述了p-范数应力聚合方法的理论基础及其在避免局部应力过高的优势,并通过Matlab代码实现完整的数值仿真流程,涵盖有限元建模、灵敏度计算、优化迭代等关键环节,适用于复杂三维结构的轻量化高强度设计。; 适合人群:具备有限元分析基础、拓扑优化背景及Matlab编程能力的研究生、科研人员或从事结构设计的工程技术人员,尤其适合致力于力学仿真优化算法开发的专业人士; 使用场景及目标:①应用于航空航天、机械制造、土木工程等领域中对结构强度和重量有高要求的设计优化;②帮助读者深入理解伴随法在应力约束优化中的应用,掌握p-范数法处理局应力约束的技术细节;③为科研复现、论文写作及工程项目提供可运行的Matlab代码参考算法验证平台; 阅读建议:建议读者结合文中提到的优化算法原理Matlab代码同步调试,重点关注敏感度推导有限元实现的衔接部分,同时推荐使用提供的网盘资源获取完整代码测试案例,以提升学习效率实践效果。
源码来自:https://pan.quark.cn/s/e1bc39762118 SmartControlAndroidMQTT 点个Star吧~ 如果不会用下载或是下载慢的,可以在到酷安下载:https://www.coolapk.com/apk/com.zyc.zcontrol 本文档还在编写中!!! 被控设备: 按键伴侣ButtonMate 直接控制墙壁开关,在不修改墙壁开关的前提下实现智能开关的效果 zTC1_a1 斐讯排插TC1重新开发固件,仅支持a1版本. zDC1 斐讯排插DC1重新开发固件. zA1 斐讯空气净化器悟净A1重新开发固件. zM1 斐讯空气检测仪悟空M1重新开发固件. zS7 斐讯体重秤S7重新开发固件.(仅支持体重,不支持体脂) zClock时钟 基于esp8266的数码管时钟 zMOPS插座 基于MOPS插座开发固件 RGBW灯 基于ESP8266的rgbw灯泡 zClock点阵时钟 基于ESP8266的点阵时钟 使用说明 此app于设备通信通过udp广播或mqtt服务器通信.udp广播为在整个局域网(255.255.255.255)的10181和10182端口通信.由于udp广播的特性,udp局域网通信不稳定,建议有条件的还是使用mqtt服务器来通信. app设置 在侧边栏点击设置,进入设置页面.可设置mqtt服务器.(此处总是通过UDP连接选项无效!) 设备控制页面 (每总设备页面不同) 界面下方的服务器已连接、服务器已断开 是指appmqtt服务器连接状态显示.设备连接状态无关. 右上角,云图标为设备同步mqtt服务器配置.由于可以自定义mqtt服务器,所以除了需要将手机连入mqtt服务器外,还需要将被控设备连入...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值