snowflake-platform

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Snowflake Platform Skill

Snowflake平台技能

Build and deploy applications on Snowflake's AI Data Cloud using the snow CLI, Cortex AI functions, Native Apps, and Snowpark.
借助snow CLI、Cortex AI函数、Native Apps和Snowpark,在Snowflake的AI数据云上构建并部署应用。

Quick Start

快速开始

Install Snowflake CLI

安装Snowflake CLI

bash
pip install snowflake-cli
snow --version  # Should show 3.14.0+
bash
pip install snowflake-cli
snow --version  # 应显示3.14.0+

Configure Connection

配置连接

bash
undefined
bash
undefined

Interactive setup

交互式设置

snow connection add
snow connection add

Or create ~/.snowflake/config.toml manually

或手动创建~/.snowflake/config.toml


```toml
[connections.default]
account = "orgname-accountname"
user = "USERNAME"
authenticator = "SNOWFLAKE_JWT"
private_key_path = "~/.snowflake/rsa_key.p8"

```toml
[connections.default]
account = "orgname-accountname"
user = "USERNAME"
authenticator = "SNOWFLAKE_JWT"
private_key_path = "~/.snowflake/rsa_key.p8"

Test Connection

测试连接

bash
snow connection test -c default
snow sql -q "SELECT CURRENT_USER(), CURRENT_ACCOUNT()"
bash
snow connection test -c default
snow sql -q "SELECT CURRENT_USER(), CURRENT_ACCOUNT()"

When to Use This Skill

适用场景

Use when:
  • Building applications on Snowflake platform
  • Using Cortex AI functions in SQL queries
  • Developing Native Apps for Marketplace
  • Setting up JWT key-pair authentication
  • Working with Snowpark Python
Don't use when:
  • Building Streamlit apps (use
    streamlit-snowflake
    skill)
  • Need data engineering/ETL patterns
  • Working with BI tools (Tableau, Looker)
适用场景:
  • 在Snowflake平台上构建应用
  • 在SQL查询中使用Cortex AI函数
  • 开发用于Marketplace的Native Apps
  • 设置JWT密钥对认证
  • 使用Snowpark Python
不适用场景:
  • 构建Streamlit应用(使用
    streamlit-snowflake
    技能)
  • 需要数据工程/ETL模式
  • 使用BI工具(Tableau、Looker)

Cortex AI Functions

Cortex AI函数

Snowflake Cortex provides LLM capabilities directly in SQL. Functions are in the
SNOWFLAKE.CORTEX
schema.
Snowflake Cortex直接在SQL中提供大语言模型(LLM)能力。函数位于
SNOWFLAKE.CORTEX
schema中。

Core Functions

核心函数

FunctionPurposeGA Status
COMPLETE
/
AI_COMPLETE
Text generation from promptGA Nov 2025
SUMMARIZE
/
AI_SUMMARIZE
Summarize textGA
TRANSLATE
/
AI_TRANSLATE
Translate between languagesGA Sep 2025
SENTIMENT
/
AI_SENTIMENT
Sentiment analysisGA Jul 2025
AI_FILTER
Natural language filteringGA Nov 2025
AI_CLASSIFY
Categorize text/imagesGA Nov 2025
AI_AGG
Aggregate insights across rowsGA Nov 2025
函数用途正式发布(GA)状态
COMPLETE
/
AI_COMPLETE
根据提示生成文本2025年11月正式发布
SUMMARIZE
/
AI_SUMMARIZE
文本摘要已正式发布
TRANSLATE
/
AI_TRANSLATE
语言翻译2025年9月正式发布
SENTIMENT
/
AI_SENTIMENT
情感分析2025年7月正式发布
AI_FILTER
自然语言过滤2025年11月正式发布
AI_CLASSIFY
文本/图像分类2025年11月正式发布
AI_AGG
跨行聚合洞察2025年11月正式发布

COMPLETE Function

COMPLETE函数

sql
-- Simple prompt
SELECT SNOWFLAKE.CORTEX.COMPLETE(
    'llama3.1-70b',
    'Explain quantum computing in one sentence'
) AS response;

-- With conversation history
SELECT SNOWFLAKE.CORTEX.COMPLETE(
    'llama3.1-70b',
    [
        {'role': 'system', 'content': 'You are a helpful assistant'},
        {'role': 'user', 'content': 'What is Snowflake?'}
    ]
) AS response;

-- With options
SELECT SNOWFLAKE.CORTEX.COMPLETE(
    'mistral-large2',
    'Summarize this document',
    {'temperature': 0.3, 'max_tokens': 500}
) AS response;
Available Models:
  • llama3.1-70b
    ,
    llama3.1-8b
    ,
    llama3.2-3b
  • mistral-large2
    ,
    mistral-7b
  • snowflake-arctic
  • gemma-7b
  • claude-3-5-sonnet
    (200K context)
Model Context Windows (Updated 2025):
ModelContext WindowBest For
Claude 3.5 Sonnet200,000 tokensLarge documents, long conversations
Llama3.1-70b128,000 tokensComplex reasoning, medium documents
Llama3.1-8b8,000 tokensSimple tasks, short text
Llama3.2-3b8,000 tokensFast inference, minimal text
Mistral-large2VariableCheck current docs
Snowflake ArcticVariableCheck current docs
Token Math: ~4 characters = 1 token. A 32,000 character document ≈ 8,000 tokens.
Error:
Input exceeds context window limit
→ Use smaller model or chunk your input.
sql
-- 简单提示
SELECT SNOWFLAKE.CORTEX.COMPLETE(
    'llama3.1-70b',
    '用一句话解释量子计算'
) AS response;

-- 带对话历史
SELECT SNOWFLAKE.CORTEX.COMPLETE(
    'llama3.1-70b',
    [
        {'role': 'system', 'content': '你是一个乐于助人的助手'},
        {'role': 'user', 'content': '什么是Snowflake?'}
    ]
) AS response;

-- 带参数选项
SELECT SNOWFLAKE.CORTEX.COMPLETE(
    'mistral-large2',
    '总结这份文档',
    {'temperature': 0.3, 'max_tokens': 500}
) AS response;
可用模型:
  • llama3.1-70b
    ,
    llama3.1-8b
    ,
    llama3.2-3b
  • mistral-large2
    ,
    mistral-7b
  • snowflake-arctic
  • gemma-7b
  • claude-3-5-sonnet
    (200K上下文窗口)
模型上下文窗口(2025年更新):
模型上下文窗口最佳适用场景
Claude 3.5 Sonnet200,000 tokens大型文档、长对话
Llama3.1-70b128,000 tokens复杂推理、中型文档
Llama3.1-8b8,000 tokens简单任务、短文本
Llama3.2-3b8,000 tokens快速推理、极简文本
Mistral-large2可变查看最新文档
Snowflake Arctic可变查看最新文档
Token计算:约4个字符=1个token。32,000字符的文档≈8,000 tokens。
错误处理
Input exceeds context window limit
→ 使用更小的模型或拆分输入内容。

SUMMARIZE Function

SUMMARIZE函数

sql
-- Single text
SELECT SNOWFLAKE.CORTEX.SUMMARIZE(article_text) AS summary
FROM articles
LIMIT 10;

-- Aggregate across rows (no context window limit)
SELECT AI_SUMMARIZE_AGG(review_text) AS all_reviews_summary
FROM product_reviews
WHERE product_id = 123;
sql
-- 单条文本摘要
SELECT SNOWFLAKE.CORTEX.SUMMARIZE(article_text) AS summary
FROM articles
LIMIT 10;

-- 跨行聚合摘要(无上下文窗口限制)
SELECT AI_SUMMARIZE_AGG(review_text) AS all_reviews_summary
FROM product_reviews
WHERE product_id = 123;

TRANSLATE Function

TRANSLATE函数

sql
-- Translate to English (auto-detect source)
SELECT SNOWFLAKE.CORTEX.TRANSLATE(
    review_text,
    '',      -- Empty = auto-detect source language
    'en'     -- Target language
) AS translated
FROM international_reviews;

-- Explicit source language
SELECT AI_TRANSLATE(
    description,
    'es',    -- Source: Spanish
    'en'     -- Target: English
) AS translated
FROM spanish_products;
sql
-- 翻译为英文(自动检测源语言)
SELECT SNOWFLAKE.CORTEX.TRANSLATE(
    review_text,
    '',      -- 空值=自动检测源语言
    'en'     -- 目标语言
) AS translated
FROM international_reviews;

-- 显式指定源语言
SELECT AI_TRANSLATE(
    description,
    'es',    -- 源语言:西班牙语
    'en'     -- 目标语言:英语
) AS translated
FROM spanish_products;

AI_FILTER (Natural Language Filtering)

AI_FILTER(自然语言过滤)

Performance: As of September 2025, AI_FILTER includes automatic optimization delivering 2-10x speedup and up to 60% token reduction for suitable queries.
sql
-- Filter with plain English
SELECT * FROM customer_feedback
WHERE AI_FILTER(
    feedback_text,
    'mentions shipping problems or delivery delays'
);

-- Combine with SQL predicates for maximum optimization
-- Query planner applies standard filters FIRST, then AI on smaller dataset
SELECT * FROM support_tickets
WHERE created_date > '2025-01-01'  -- Standard filter applied first
  AND AI_FILTER(description, 'customer is angry or frustrated');
Best Practice: Always combine AI_FILTER with traditional SQL predicates (date ranges, categories, etc.) to reduce the dataset before AI processing. This maximizes the automatic optimization benefits.
Throttling: During peak usage, AI function requests may be throttled with retry-able errors. Implement exponential backoff for production applications (see Known Issue #10).
性能优化:截至2025年9月,AI_FILTER包含自动优化功能,可为合适的查询带来2-10倍的速度提升,最多减少60%的token使用量。
sql
-- 用自然语言过滤
SELECT * FROM customer_feedback
WHERE AI_FILTER(
    feedback_text,
    '提及运输问题或配送延迟'
);

-- 结合SQL谓词实现最大优化
-- 查询规划器会先应用标准过滤,再对更小的数据集执行AI过滤
SELECT * FROM support_tickets
WHERE created_date > '2025-01-01'  -- 先应用标准过滤
  AND AI_FILTER(description, '客户感到愤怒或沮丧');
最佳实践:始终将AI_FILTER与传统SQL谓词(日期范围、分类等)结合使用,在AI处理之前先缩小数据集规模,以最大化自动优化的收益。
限流处理:在高峰使用时段,AI函数请求可能会被限流并返回可重试错误。生产应用中需实现指数退避重试机制(详见已知问题#10)。

AI_CLASSIFY

AI_CLASSIFY

sql
-- Categorize support tickets
SELECT
    ticket_id,
    AI_CLASSIFY(
        description,
        ['billing', 'technical', 'shipping', 'other']
    ) AS category
FROM support_tickets;
sql
-- 分类支持工单
SELECT
    ticket_id,
    AI_CLASSIFY(
        description,
        ['账单', '技术', '运输', '其他']
    ) AS category
FROM support_tickets;

Billing

计费说明

Cortex AI functions bill based on tokens:
  • ~4 characters = 1 token
  • Both input AND output tokens are billed
  • Rates vary by model (larger models cost more)
Cost Management at Scale (Community-sourced):
Real-world production case study showed a single AI_COMPLETE query processing 1.18 billion records cost nearly $5K in credits. Cost drivers to watch:
  1. Cross-region inference: Models not available in your region incur additional data transfer costs
  2. Warehouse idle time: Unused compute still bills, but aggressive auto-suspend adds resume overhead
  3. Large table joins: Complex queries with AI functions multiply costs
sql
-- This seemingly simple query can be expensive at scale
SELECT
    product_id,
    AI_COMPLETE('mistral-large2', 'Summarize: ' || review_text) as summary
FROM product_reviews  -- 1 billion rows
WHERE created_date > '2024-01-01';

-- Cost = (input tokens + output tokens) × row count × model rate
-- At scale, this adds up fast
Best Practices:
  • Filter datasets BEFORE applying AI functions
  • Right-size warehouses (don't over-provision)
  • Monitor credit consumption with QUERY_HISTORY views
  • Consider batch processing instead of row-by-row AI operations
Source: The Hidden Cost of Snowflake Cortex AI (Community blog with billing evidence)
Cortex AI函数基于token计费:
  • 约4个字符=1个token
  • 输入和输出token都会被计费
  • 费率因模型而异(大型模型成本更高)
大规模成本管理(社区贡献):
实际生产案例显示,一个处理11.8亿条记录的AI_COMPLETE查询花费了近5000美元的积分。需要关注的成本驱动因素:
  1. 跨区域推理:如果您的区域没有可用模型,会产生额外的数据传输成本
  2. 仓库空闲时间:未使用的计算资源仍会计费,但过于激进的自动暂停会增加恢复开销
  3. 大型表连接:包含AI函数的复杂查询会成倍增加成本
sql
-- 这个看似简单的查询在大规模场景下可能成本高昂
SELECT
    product_id,
    AI_COMPLETE('mistral-large2', '总结:' || review_text) as summary
FROM product_reviews  -- 10亿行数据
WHERE created_date > '2024-01-01';

-- 成本 = (输入token + 输出token) × 行数 × 模型费率
-- 在大规模场景下,成本会快速累积
最佳实践
  • 在应用AI函数之前先过滤数据集
  • 合理设置仓库规模(不要过度配置)
  • 使用QUERY_HISTORY视图监控积分消耗
  • 考虑使用批处理代替逐行AI操作
来源Snowflake Cortex AI的隐性成本(包含计费证据的社区博客)

Authentication

认证机制

JWT Key-Pair Authentication

JWT密钥对认证

Critical: Snowflake uses TWO account identifier formats:
FormatExampleUsed For
Organization-Account
irjoewf-wq46213
REST API URLs, connection config
Account Locator
NZ90655
JWT claims (
iss
,
sub
)
These are NOT interchangeable!
关键注意事项:Snowflake使用两种账户标识符格式:
格式示例用途
组织-账户格式
irjoewf-wq46213
REST API URL、连接配置
账户定位器
NZ90655
JWT声明(
iss
,
sub
这两种格式不可互换!

Discover Your Account Locator

查看您的账户定位器

sql
SELECT CURRENT_ACCOUNT();  -- Returns: NZ90655
sql
SELECT CURRENT_ACCOUNT();  -- 返回:NZ90655

Generate RSA Key Pair

生成RSA密钥对

bash
undefined
bash
undefined

Generate private key (PKCS#8 format required)

生成私钥(必须为PKCS#8格式)

openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out ~/.snowflake/rsa_key.p8 -nocrypt
openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out ~/.snowflake/rsa_key.p8 -nocrypt

Generate public key

生成公钥

openssl rsa -in ~/.snowflake/rsa_key.p8 -pubout -out ~/.snowflake/rsa_key.pub
openssl rsa -in ~/.snowflake/rsa_key.p8 -pubout -out ~/.snowflake/rsa_key.pub

Get fingerprint for JWT claims

获取JWT声明所需的指纹

openssl rsa -in ~/.snowflake/rsa_key.p8 -pubout -outform DER |
openssl dgst -sha256 -binary | openssl enc -base64
undefined
openssl rsa -in ~/.snowflake/rsa_key.p8 -pubout -outform DER |
openssl dgst -sha256 -binary | openssl enc -base64
undefined

Register Public Key with User

向用户注册公钥

sql
-- In Snowflake worksheet (requires ACCOUNTADMIN or SECURITYADMIN)
ALTER USER my_user SET RSA_PUBLIC_KEY='MIIBIjANBgkq...';
sql
-- 在Snowflake工作表中执行(需要ACCOUNTADMIN或SECURITYADMIN权限)
ALTER USER my_user SET RSA_PUBLIC_KEY='MIIBIjANBgkq...';

JWT Claim Format

JWT声明格式

iss: ACCOUNT_LOCATOR.USERNAME.SHA256:fingerprint
sub: ACCOUNT_LOCATOR.USERNAME
Example:
iss: NZ90655.JEZWEB.SHA256:jpZO6LvU2SpKd8tE61OGfas5ZXpfHloiJd7XHLPDEEA=
sub: NZ90655.JEZWEB
iss: ACCOUNT_LOCATOR.USERNAME.SHA256:fingerprint
sub: ACCOUNT_LOCATOR.USERNAME
示例:
iss: NZ90655.JEZWEB.SHA256:jpZO6LvU2SpKd8tE61OGfas5ZXpfHloiJd7XHLPDEEA=
sub: NZ90655.JEZWEB

SPCS Container Authentication (v4.2.0+)

SPCS容器认证(v4.2.0+)

New in January 2026: Connector automatically detects and uses SPCS service identifier tokens when running inside Snowpark Container Services.
python
undefined
2026年1月新增功能:当在Snowpark Container Services中运行时,连接器会自动检测并使用SPCS服务标识符令牌。
python
undefined

No special configuration needed inside SPCS containers

SPCS容器内无需特殊配置

import snowflake.connector
import snowflake.connector

Auto-detects SPCS_TOKEN environment variable

自动检测SPCS_TOKEN环境变量

conn = snowflake.connector.connect()

This enables seamless authentication from containerized Snowpark services without explicit credentials.

**Source**: [Release v4.2.0](https://github.com/snowflakedb/snowflake-connector-python/releases/tag/v4.2.0)
conn = snowflake.connector.connect()

这使得容器化的Snowpark服务无需显式凭证即可实现无缝认证。

**来源**:[v4.2.0版本发布说明](https://github.com/snowflakedb/snowflake-connector-python/releases/tag/v4.2.0)

Snow CLI Commands

Snow CLI命令

Project Management

项目管理

bash
undefined
bash
undefined

Initialize project

初始化项目

snow init
snow init

Execute SQL

执行SQL

snow sql -q "SELECT 1" snow sql -f query.sql
snow sql -q "SELECT 1" snow sql -f query.sql

View logs

查看日志

snow logs
undefined
snow logs
undefined

Native App Commands

Native App命令

bash
undefined
bash
undefined

Development

开发阶段

snow app run # Deploy and run locally snow app deploy # Upload to stage only snow app teardown # Remove app
snow app run # 部署并本地运行 snow app deploy # 仅上传到stage snow app teardown # 移除应用

Versioning

版本管理

snow app version create V1_0 snow app version list snow app version drop V1_0
snow app version create V1_0 snow app version list snow app version drop V1_0

Publishing

发布应用

snow app publish --version V1_0 --patch 0
snow app publish --version V1_0 --patch 0

Release Channels

发布渠道

snow app release-channel list snow app release-channel add-version --channel ALPHA --version V1_0 snow app release-directive set default --version V1_0 --patch 0 --channel DEFAULT
undefined
snow app release-channel list snow app release-channel add-version --channel ALPHA --version V1_0 snow app release-directive set default --version V1_0 --patch 0 --channel DEFAULT
undefined

Streamlit Commands

Streamlit命令

bash
snow streamlit deploy --replace
snow streamlit deploy --replace --open
bash
snow streamlit deploy --replace
snow streamlit deploy --replace --open

Stage Commands

Stage命令

bash
snow stage list
snow stage copy @my_stage/file.txt ./local/
bash
snow stage list
snow stage copy @my_stage/file.txt ./local/

Native App Development

Native App开发

Project Structure

项目结构

my_native_app/
├── snowflake.yml           # Project config
├── manifest.yml            # App manifest
├── setup_script.sql        # Installation script
├── app/
│   └── streamlit/
│       ├── environment.yml
│       └── streamlit_app.py
└── scripts/
    └── setup.sql
my_native_app/
├── snowflake.yml           # 项目配置文件
├── manifest.yml            # 应用清单文件
├── setup_script.sql        # 安装脚本
├── app/
│   └── streamlit/
│       ├── environment.yml
│       └── streamlit_app.py
└── scripts/
    └── setup.sql

snowflake.yml

snowflake.yml

yaml
definition_version: 2

native_app:
  name: my_app
  package:
    name: my_app_pkg
    distribution: external    # For marketplace
  application:
    name: my_app
  source_stage: stage/dev
  artifacts:
    - src: manifest.yml
      dest: manifest.yml
    - src: setup_script.sql
      dest: setup_script.sql
    - src: app/streamlit/environment.yml
      dest: streamlit/environment.yml
    - src: app/streamlit/streamlit_app.py
      dest: streamlit/streamlit_app.py
  enable_release_channels: true  # For ALPHA/BETA channels
yaml
definition_version: 2

native_app:
  name: my_app
  package:
    name: my_app_pkg
    distribution: external    # 用于Marketplace发布
  application:
    name: my_app
  source_stage: stage/dev
  artifacts:
    - src: manifest.yml
      dest: manifest.yml
    - src: setup_script.sql
      dest: setup_script.sql
    - src: app/streamlit/environment.yml
      dest: streamlit/environment.yml
    - src: app/streamlit/streamlit_app.py
      dest: streamlit/streamlit_app.py
  enable_release_channels: true  # 启用ALPHA/BETA渠道

manifest.yml

manifest.yml

yaml
manifest_version: 1

artifacts:
  setup_script: setup_script.sql
  default_streamlit: streamlit/streamlit_app.py
yaml
manifest_version: 1

artifacts:
  setup_script: setup_script.sql
  default_streamlit: streamlit/streamlit_app.py

Note: Do NOT include privileges section - Native Apps can't declare privileges

注意:不要包含权限部分 - Native Apps无法声明权限

undefined
undefined

External Access Integration

外部访问集成

Native Apps calling external APIs need this setup:
sql
-- 1. Create network rule (in a real database, NOT app package)
CREATE DATABASE IF NOT EXISTS MY_APP_UTILS;

CREATE OR REPLACE NETWORK RULE MY_APP_UTILS.PUBLIC.api_rule
  MODE = EGRESS
  TYPE = HOST_PORT
  VALUE_LIST = ('api.example.com:443');

-- 2. Create integration
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION my_app_integration
  ALLOWED_NETWORK_RULES = (MY_APP_UTILS.PUBLIC.api_rule)
  ENABLED = TRUE;

-- 3. Grant to app
GRANT USAGE ON INTEGRATION my_app_integration
  TO APPLICATION MY_APP;

-- 4. CRITICAL: Attach to Streamlit (must repeat after EVERY deploy!)
ALTER STREAMLIT MY_APP.config_schema.my_streamlit
  SET EXTERNAL_ACCESS_INTEGRATIONS = (my_app_integration);
Warning: Step 4 resets on every
snow app run
. Must re-run after each deploy!
调用外部API的Native Apps需要进行以下设置:
sql
-- 1. 创建网络规则(在真实数据库中创建,而非应用包)
CREATE DATABASE IF NOT EXISTS MY_APP_UTILS;

CREATE OR REPLACE NETWORK RULE MY_APP_UTILS.PUBLIC.api_rule
  MODE = EGRESS
  TYPE = HOST_PORT
  VALUE_LIST = ('api.example.com:443');

-- 2. 创建集成
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION my_app_integration
  ALLOWED_NETWORK_RULES = (MY_APP_UTILS.PUBLIC.api_rule)
  ENABLED = TRUE;

-- 3. 授予应用访问权限
GRANT USAGE ON INTEGRATION my_app_integration
  TO APPLICATION MY_APP;

-- 4. 关键步骤:关联到Streamlit(每次部署后必须重复执行!)
ALTER STREAMLIT MY_APP.config_schema.my_streamlit
  SET EXTERNAL_ACCESS_INTEGRATIONS = (my_app_integration);
警告:步骤4会在每次执行
snow app run
后重置,每次部署后必须重新执行!

Shared Data Pattern

共享数据模式

When your Native App needs data from an external database:
sql
-- 1. Create shared_data schema in app package
CREATE SCHEMA IF NOT EXISTS MY_APP_PKG.SHARED_DATA;

-- 2. Create views referencing external database
CREATE OR REPLACE VIEW MY_APP_PKG.SHARED_DATA.MY_VIEW AS
SELECT * FROM EXTERNAL_DB.SCHEMA.TABLE;

-- 3. Grant REFERENCE_USAGE (CRITICAL!)
GRANT REFERENCE_USAGE ON DATABASE EXTERNAL_DB
  TO SHARE IN APPLICATION PACKAGE MY_APP_PKG;

-- 4. Grant access to share
GRANT USAGE ON SCHEMA MY_APP_PKG.SHARED_DATA
  TO SHARE IN APPLICATION PACKAGE MY_APP_PKG;
GRANT SELECT ON ALL VIEWS IN SCHEMA MY_APP_PKG.SHARED_DATA
  TO SHARE IN APPLICATION PACKAGE MY_APP_PKG;
In
setup_script.sql
, reference
shared_data.view_name
(NOT the original database).
当您的Native App需要访问外部数据库的数据时:
sql
-- 1. 在应用包中创建shared_data schema
CREATE SCHEMA IF NOT EXISTS MY_APP_PKG.SHARED_DATA;

-- 2. 创建引用外部数据库的视图
CREATE OR REPLACE VIEW MY_APP_PKG.SHARED_DATA.MY_VIEW AS
SELECT * FROM EXTERNAL_DB.SCHEMA.TABLE;

-- 3. 授予REFERENCE_USAGE权限(关键!)
GRANT REFERENCE_USAGE ON DATABASE EXTERNAL_DB
  TO SHARE IN APPLICATION PACKAGE MY_APP_PKG;

-- 4. 授予共享访问权限
GRANT USAGE ON SCHEMA MY_APP_PKG.SHARED_DATA
  TO SHARE IN APPLICATION PACKAGE MY_APP_PKG;
GRANT SELECT ON ALL VIEWS IN SCHEMA MY_APP_PKG.SHARED_DATA
  TO SHARE IN APPLICATION PACKAGE MY_APP_PKG;
setup_script.sql
中,引用
shared_data.view_name
(而非原始数据库)。

Marketplace Publishing

Marketplace发布

Security Review Workflow

安全审核流程

bash
undefined
bash
undefined

1. Deploy app

1. 部署应用

snow app run
snow app run

2. Create version

2. 创建版本

snow app version create V1_0
snow app version create V1_0

3. Check security review status

3. 检查安全审核状态

snow app version list
snow app version list

Wait for review_status = APPROVED

等待review_status = APPROVED

4. Set release directive

4. 设置发布指令

snow app release-directive set default --version V1_0 --patch 0 --channel DEFAULT
snow app release-directive set default --version V1_0 --patch 0 --channel DEFAULT

5. Create listing in Snowsight Provider Studio (UI only)

5. 在Snowsight Provider Studio中创建列表(仅支持UI操作)

undefined
undefined

Security Review Statuses

安全审核状态

StatusMeaningAction
NOT_REVIEWED
Scan hasn't runCheck DISTRIBUTION is EXTERNAL
IN_PROGRESS
Scan runningWait
APPROVED
PassedCan publish
REJECTED
FailedFix issues or appeal
MANUAL_REVIEW
Human reviewingWait (can take days)
Triggers manual review: External access integrations, Streamlit components, network calls.
状态含义操作
NOT_REVIEWED
尚未执行扫描检查DISTRIBUTION是否设置为EXTERNAL
IN_PROGRESS
扫描进行中等待
APPROVED
审核通过可发布
REJECTED
审核失败修复问题或申诉
MANUAL_REVIEW
人工审核中等待(可能需要数天)
触发人工审核的场景:外部访问集成、Streamlit组件、网络调用。

Provider Studio Fields

Provider Studio字段

FieldMax LengthNotes
Title72 charsApp name
Subtitle128 charsOne-liner
Description10,000 charsHTML editor
Business Needs6 maxSelect from dropdown
Quick Start Examples10 maxTitle + Description + SQL
Data DictionaryRequiredMandatory for data listings (2025)
字段最大长度说明
Title72字符应用名称
Subtitle128字符一句话描述
Description10,000字符HTML编辑器
Business Needs最多6个从下拉列表选择
Quick Start Examples最多10个标题 + 描述 + SQL
Data Dictionary必填2025年起数据列表必填

Paid Listing Prerequisites

付费列表前提条件

#Requirement
1Full Snowflake account (not trial)
2ACCOUNTADMIN role
3Provider Profile approved
4Stripe account configured
5Provider & Consumer Terms accepted
6Contact Marketplace Ops
Note: Cannot convert free listing to paid. Must create new listing.
#要求
1完整的Snowflake账户(非试用版)
2ACCOUNTADMIN角色
3供应商资料已审核通过
4已配置Stripe账户
5已接受供应商与消费者条款
6联系Marketplace运营团队
注意:无法将免费列表转换为付费列表,必须创建新的列表。

Snowpark Python

Snowpark Python

Session Setup

会话设置

python
from snowflake.snowpark import Session

connection_params = {
    "account": "orgname-accountname",
    "user": "USERNAME",
    "password": "PASSWORD",  # Or use private_key_path
    "warehouse": "COMPUTE_WH",
    "database": "MY_DB",
    "schema": "PUBLIC"
}

session = Session.builder.configs(connection_params).create()
python
from snowflake.snowpark import Session

connection_params = {
    "account": "orgname-accountname",
    "user": "USERNAME",
    "password": "PASSWORD",  # 或使用private_key_path
    "warehouse": "COMPUTE_WH",
    "database": "MY_DB",
    "schema": "PUBLIC"
}

session = Session.builder.configs(connection_params).create()

DataFrame Operations

DataFrame操作

python
undefined
python
undefined

Read table

读取表

df = session.table("MY_TABLE")
df = session.table("MY_TABLE")

Filter and select

过滤与选择

result = df.filter(df["STATUS"] == "ACTIVE")
.select("ID", "NAME", "CREATED_AT")
.sort("CREATED_AT", ascending=False)
result = df.filter(df["STATUS"] == "ACTIVE")
.select("ID", "NAME", "CREATED_AT")
.sort("CREATED_AT", ascending=False)

Execute

执行并显示结果

result.show()
result.show()

Collect to Python

收集到Python本地

rows = result.collect()
undefined
rows = result.collect()
undefined

Row Access (Common Gotcha)

行访问注意事项(常见误区)

python
undefined
python
undefined

WRONG - dict() doesn't work on Snowpark Row

错误示例 - dict()无法处理Snowpark Row对象

config = dict(result[0])
config = dict(result[0])

CORRECT - Access columns explicitly

正确示例 - 显式访问列

row = result[0] config = { 'COLUMN_A': row['COLUMN_A'], 'COLUMN_B': row['COLUMN_B'], }
undefined
row = result[0] config = { 'COLUMN_A': row['COLUMN_A'], 'COLUMN_B': row['COLUMN_B'], }
undefined

DML Statistics (v4.2.0+)

DML统计信息(v4.2.0+)

New in January 2026:
SnowflakeCursor.stats
property exposes granular DML statistics for operations where
rowcount
is insufficient (e.g., CTAS queries).
python
undefined
2026年1月新增功能
SnowflakeCursor.stats
属性公开了细粒度的DML统计信息,适用于
rowcount
不足以提供信息的操作(例如CTAS查询)。
python
undefined

Before v4.2.0 - rowcount returns -1 for CTAS

v4.2.0之前 - CTAS查询的rowcount返回-1

cursor.execute("CREATE TABLE new_table AS SELECT * FROM source WHERE active = true") print(cursor.rowcount) # Returns -1 (not helpful!)
cursor.execute("CREATE TABLE new_table AS SELECT * FROM source WHERE active = true") print(cursor.rowcount) # 返回-1(无帮助!)

After v4.2.0 - stats property shows actual row counts

v4.2.0之后 - stats属性显示实际行数

cursor.execute("CREATE TABLE new_table AS SELECT * FROM source WHERE active = true") print(cursor.stats) # Returns {'rows_inserted': 1234, 'duplicates': 0, ...}

**Source**: [Release v4.2.0](https://github.com/snowflakedb/snowflake-connector-python/releases/tag/v4.2.0)
cursor.execute("CREATE TABLE new_table AS SELECT * FROM source WHERE active = true") print(cursor.stats) # 返回{'rows_inserted': 1234, 'duplicates': 0, ...}

**来源**:[v4.2.0版本发布说明](https://github.com/snowflakedb/snowflake-connector-python/releases/tag/v4.2.0)

UDFs and Stored Procedures

UDF与存储过程

python
from snowflake.snowpark.functions import udf, sproc
python
from snowflake.snowpark.functions import udf, sproc

Register UDF

注册UDF

@udf(name="my_udf", replace=True) def my_udf(x: int) -> int: return x * 2
@udf(name="my_udf", replace=True) def my_udf(x: int) -> int: return x * 2

Register Stored Procedure

注册存储过程

@sproc(name="my_sproc", replace=True) def my_sproc(session: Session, table_name: str) -> str: df = session.table(table_name) count = df.count() return f"Row count: {count}"
undefined
@sproc(name="my_sproc", replace=True) def my_sproc(session: Session, table_name: str) -> str: df = session.table(table_name) count = df.count() return f"行数:{count}"
undefined

REST API (SQL API v2)

REST API(SQL API v2)

The REST API is the foundation for programmatic Snowflake access from Cloudflare Workers.
REST API是从Cloudflare Workers以编程方式访问Snowflake的基础。

Endpoint

端点地址

https://{org-account}.snowflakecomputing.com/api/v2/statements
https://{org-account}.snowflakecomputing.com/api/v2/statements

Required Headers (CRITICAL)

必填请求头(关键)

ALL requests must include these headers - missing
Accept
causes silent failures:
typescript
const headers = {
  'Authorization': `Bearer ${jwt}`,
  'Content-Type': 'application/json',
  'Accept': 'application/json',  // REQUIRED - "null" error if missing
  'User-Agent': 'MyApp/1.0',
};
所有请求必须包含以下请求头 - 缺少
Accept
会导致静默失败:
typescript
const headers = {
  'Authorization': `Bearer ${jwt}`,
  'Content-Type': 'application/json',
  'Accept': 'application/json',  // 必填 - 缺少会返回"null"错误
  'User-Agent': 'MyApp/1.0',
};

Async Query Handling

异步查询处理

Even simple queries return async (HTTP 202). Always implement polling:
typescript
// Submit returns statementHandle, not results
const submit = await fetch(url, { method: 'POST', headers, body });
const { statementHandle } = await submit.json();

// Poll until complete
while (true) {
  const status = await fetch(`${url}/${statementHandle}`, { headers });
  if (status.status === 200) break;  // Complete
  if (status.status === 202) {
    await sleep(2000);  // Still running
    continue;
  }
}
即使是简单的查询也会返回异步结果(HTTP 202状态码),必须始终实现轮询机制:
typescript
// 提交请求返回statementHandle,而非结果
const submit = await fetch(url, { method: 'POST', headers, body });
const { statementHandle } = await submit.json();

// 轮询直到查询完成
while (true) {
  const status = await fetch(`${url}/${statementHandle}`, { headers });
  if (status.status === 200) break;  // 查询完成
  if (status.status === 202) {
    await sleep(2000);  // 仍在运行
    continue;
  }
}

Workers Subrequest Limits

Workers子请求限制

PlanLimitSafe Polling
Free5045 attempts @ 2s = 90s max
Paid1,000100 attempts @ 500ms = 50s max
套餐限制安全轮询策略
免费版5045次尝试 × 2秒 = 最长90秒
付费版1,000100次尝试 × 500毫秒 = 最长50秒

Fetch Timeouts

请求超时设置

Workers
fetch()
has no default timeout. Always use AbortController:
typescript
const response = await fetch(url, {
  signal: AbortSignal.timeout(30000),  // 30 seconds
  headers,
});
Workers的
fetch()
没有默认超时,必须始终使用AbortController:
typescript
const response = await fetch(url, {
  signal: AbortSignal.timeout(30000),  // 30秒超时
  headers,
});

Cancel on Timeout

超时取消查询

Cancel queries when timeout occurs to avoid warehouse costs:
POST /api/v2/statements/{statementHandle}/cancel
See
templates/snowflake-rest-client.ts
for complete implementation.
当发生超时时,取消查询以避免仓库成本:
POST /api/v2/statements/{statementHandle}/cancel
完整实现请参考
templates/snowflake-rest-client.ts

Known Issues

已知问题

1. Account Identifier Confusion

1. 账户标识符混淆

Symptom: JWT auth fails silently, queries don't appear in Query History.
Cause: Using org-account format in JWT claims instead of account locator.
Fix: Use
SELECT CURRENT_ACCOUNT()
to get the actual account locator.
症状:JWT认证静默失败,查询未出现在查询历史中。
原因:在JWT声明中使用了组织-账户格式,而非账户定位器。
解决方法:使用
SELECT CURRENT_ACCOUNT()
获取实际的账户定位器。

2. External Access Reset

2. 外部访问权限重置

Symptom: API calls fail after
snow app run
.
Cause: External access integration attachment resets on every deploy.
Fix: Re-run
ALTER STREAMLIT ... SET EXTERNAL_ACCESS_INTEGRATIONS
after each deploy.
症状:执行
snow app run
后API调用失败。
原因:外部访问集成的关联会在每次部署后重置。
解决方法:每次部署后重新执行
ALTER STREAMLIT ... SET EXTERNAL_ACCESS_INTEGRATIONS

3. Release Channel Syntax

3. 发布渠道语法错误

Symptom:
ALTER APPLICATION PACKAGE ... SET DEFAULT RELEASE DIRECTIVE
fails.
Cause: Legacy SQL syntax doesn't work with release channels enabled.
Fix: Use snow CLI:
snow app release-directive set default --version V1_0 --patch 0 --channel DEFAULT
症状
ALTER APPLICATION PACKAGE ... SET DEFAULT RELEASE DIRECTIVE
执行失败。
原因:旧版SQL语法在启用发布渠道后无法使用。
解决方法:使用Snow CLI命令:
snow app release-directive set default --version V1_0 --patch 0 --channel DEFAULT

4. Artifact Nesting

4. 工件嵌套问题

Symptom: Files appear in
streamlit/streamlit/
instead of
streamlit/
.
Cause: Directory mappings in snowflake.yml nest the folder name.
Fix: List individual files explicitly in artifacts, not directories.
症状:文件出现在
streamlit/streamlit/
目录下,而非
streamlit/
原因:snowflake.yml中的目录映射导致文件夹名称嵌套。
解决方法:在artifacts中显式列出单个文件,而非目录。

5. REFERENCE_USAGE Missing

5. 缺少REFERENCE_USAGE权限

Symptom: "A view that is added to the shared content cannot reference objects from other databases"
Cause: Missing
GRANT REFERENCE_USAGE ON DATABASE
for shared data.
Fix: Always grant REFERENCE_USAGE before
snow app run
when using external databases.
症状:"添加到共享内容的视图无法引用其他数据库中的对象"
原因:使用外部数据库时缺少
GRANT REFERENCE_USAGE ON DATABASE
权限。
解决方法:在执行
snow app run
前,始终授予REFERENCE_USAGE权限。

6. REST API Missing Accept Header

6. REST API缺少Accept请求头

Symptom: "Unsupported Accept header null is specified" on polling requests.
Cause: Initial request had
Accept: application/json
but polling request didn't.
Fix: Use consistent headers helper function for ALL requests (submit, poll, cancel).
症状:轮询请求时出现"Unsupported Accept header null is specified"错误。
原因:初始请求包含
Accept: application/json
,但轮询请求未包含。
解决方法:对所有请求(提交、轮询、取消)使用统一的请求头辅助函数。

7. Workers Fetch Hangs Forever

7. Workers Fetch请求无限挂起

Symptom: Worker hangs indefinitely waiting for Snowflake response.
Cause: Cloudflare Workers'
fetch()
has no default timeout.
Fix: Always use
AbortSignal.timeout(30000)
on all Snowflake requests.
症状:Worker无限等待Snowflake响应。
原因:Cloudflare Workers的
fetch()
没有默认超时。
解决方法:对所有Snowflake请求始终使用
AbortSignal.timeout(30000)

8. Too Many Subrequests

8. 子请求数量过多

Symptom: "Too many subrequests" error during polling.
Cause: Polling every 1 second × 600 attempts = 600 subrequests exceeds limits.
Fix: Poll every 2-5 seconds, limit to 45 (free) or 100 (paid) attempts.
症状:轮询时出现"Too many subrequests"错误。
原因:每秒轮询1次 × 600次尝试 = 600次子请求,超过限制。
解决方法:每2-5秒轮询一次,限制尝试次数为45次(免费版)或100次(付费版)。

9. Warehouse Not Auto-Resuming (Perceived)

9. 仓库未自动恢复(感知问题)

Symptom: Queries return statementHandle but never complete (code 090001 indefinitely).
Cause:
090001
means "running" not error. Warehouse IS resuming, just takes time.
Fix: Auto-resume works. Wait longer or explicitly resume first:
POST /api/v2/warehouses/{wh}:resume
症状:查询返回statementHandle但从未完成(持续返回代码090001)。
原因
090001
表示"运行中"而非错误,仓库正在恢复,只是需要时间。
解决方法:自动恢复功能正常,等待更长时间或显式恢复仓库:
POST /api/v2/warehouses/{wh}:resume

10. Memory Leaks in Connector 4.x (Active Issue)

10. Connector 4.x版本中的内存泄漏(活跃问题)

Error: Long-running Python applications show memory growth over time Source: GitHub Issue #2727, #2725 Affects: snowflake-connector-python 4.0.0 - 4.2.0
Why It Happens:
  • SessionManager
    uses
    defaultdict
    which prevents garbage collection
  • SnowflakeRestful.fetch()
    holds references that leak during query execution
Prevention: Reuse connections rather than creating new ones repeatedly. Fix is in progress via PR #2741 and PR #2726.
python
undefined
错误:长时间运行的Python应用随时间推移出现内存增长。
影响版本:snowflake-connector-python 4.0.0 - 4.2.0
问题原因
  • SessionManager
    使用
    defaultdict
    导致无法垃圾回收
  • SnowflakeRestful.fetch()
    在查询执行期间持有引用导致泄漏
预防措施: 重用连接而非反复创建新连接。修复计划通过PR #2741PR #2726实现。
python
undefined

AVOID - creates new connection each iteration

避免 - 每次迭代创建新连接

for i in range(1000): conn = snowflake.connector.connect(...) cursor = conn.cursor() cursor.execute("SELECT 1") cursor.close() conn.close()
for i in range(1000): conn = snowflake.connector.connect(...) cursor = conn.cursor() cursor.execute("SELECT 1") cursor.close() conn.close()

BETTER - reuse connection

推荐 - 重用连接

conn = snowflake.connector.connect(...) cursor = conn.cursor() for i in range(1000): cursor.execute("SELECT 1") cursor.close() conn.close()

**Status**: Fix expected in connector v4.3.0 or later
conn = snowflake.connector.connect(...) cursor = conn.cursor() for i in range(1000): cursor.execute("SELECT 1") cursor.close() conn.close()

**状态**:预计在connector v4.3.0或更高版本中修复。

11. AI Function Throttling During Peak Usage

11. 高峰时段AI函数限流

Error: "Request throttled due to high usage. Please retry." Source: Snowflake Cortex Documentation Affects: All Cortex AI functions (COMPLETE, FILTER, CLASSIFY, etc.)
Why It Happens: AI/LLM requests may be throttled during high usage periods to manage platform capacity. Throttled requests return errors and require manual retries.
Prevention: Implement retry logic with exponential backoff:
python
import time
import snowflake.connector

def execute_with_retry(cursor, query, max_retries=3):
    for attempt in range(max_retries):
        try:
            return cursor.execute(query).fetchall()
        except snowflake.connector.errors.DatabaseError as e:
            if "throttled" in str(e).lower() and attempt < max_retries - 1:
                wait_time = 2 ** attempt  # Exponential backoff
                time.sleep(wait_time)
            else:
                raise
Status: Documented behavior, no fix planned
错误:"Request throttled due to high usage. Please retry."
影响范围:所有Cortex AI函数(COMPLETE、FILTER、CLASSIFY等)
问题原因: 在高使用时段,AI/LLM请求可能会被限流以管理平台容量。被限流的请求会返回错误,需要手动重试。
预防措施: 实现带指数退避的重试逻辑:
python
import time
import snowflake.connector

def execute_with_retry(cursor, query, max_retries=3):
    for attempt in range(max_retries):
        try:
            return cursor.execute(query).fetchall()
        except snowflake.connector.errors.DatabaseError as e:
            if "throttled" in str(e).lower() and attempt < max_retries - 1:
                wait_time = 2 ** attempt  # 指数退避
                time.sleep(wait_time)
            else:
                raise
状态:已记录的行为,暂无修复计划。

References

参考资料

Related Skills

相关技能

  • streamlit-snowflake
    - Streamlit in Snowflake apps
  • streamlit-snowflake
    - Snowflake应用中的Streamlit开发