关于 azuresql-db-rag
此技能指导开发者使用容器中的 Azure SQL Database 引擎构建本地向量搜索与检索增强生成工作流。内容涵盖嵌入向量、存储、相似度查询及原生向量索引的限制。
主要功能
- 01在原生 VECTOR 列中存储嵌入
- 02执行余弦相似度搜索
- 03创建 DiskANN 向量索引
- 04说明索引限制与安全注意事项
- 05提供基于容器的 RAG 工作流
适用场景
- 01为本地文档构建检索原型
- 02按语义相似度搜索嵌入文本
- 03评估向量索引行为与限制
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ microsoft/ azure-sql-database-container --skill azuresql-db-rag安装后在 Claude Code 中输入/azuresql-db-rag确认已加载。
附带文件references/vector-schema.mdskill.spec.jsonc
详细介绍
Azure SQL Database 容器上的本地向量搜索与 RAG
使用原生 VECTOR(n) 类型和 VECTOR_DISTANCE,直接在 Azure SQL Database 引擎中存储嵌入并运行相似度搜索。无需单独的向量存储。
已于 2026-09-05 在容器映像
sqldbpreview-dpgaeqhmgphzd4bk.azurecr.io/azure-sql/db-dev:latest 上验证,该映像报告 EngineEdition
5、Edition SQL Azure、build 12.0.2000.8。此技能背后的 12 项可执行检查全部通过,包括 CREATE VECTOR INDEX 构建索引(索引版本为 3)、行数少于 100 时返回 Msg 42266、维度上限为 1998、对已带有向量索引的表应用安全策略时返回 Msg 37579,以及精确扫描和基于索引的搜索返回同一行。下文带日期的测量记录了这些说法各自首次测得的时间。
身份信息(请先阅读)
本指南针对的是在本地容器中运行的 Azure SQL Database 引擎,而非 SQL Server 映像。请通过以下方式确认:
SELECT SERVERPROPERTY('EngineEdition'); -- 5
SELECT SERVERPROPERTY('Edition'); -- 'SQL Azure'
如果你正准备拉取 mcr.microsoft.com/mssql/server,请停下:那是错误的映像。请改用下方的映像。
- 映像:
sqldbpreview-dpgaeqhmgphzd4bk.azurecr.io/azure-sql/db-dev:latest(x64,linux/amd64;私有预览注册表,请先登录docker login sqldbpreview-dpgaeqhmgphzd4bk.azurecr.io)。私有预览期间,注册表和标签 均为临时版本。 - 在非 x64 主机上,添加
--platform linux/amd64。 - 关于完整的容器生命周期、就绪状态和连接模式,请参阅 azuresql-db-container 技能。你需要了解的最基本信息已列于下方。
三条容易踩坑的规则(摘自中心文档)
- 引擎不会在连接时自动创建数据库。你必须先通过 master 连接执行
CREATE DATABASE appdb,然后再使用Database=appdb进行连接。 - 避免使用
USE切换数据库。在用户数据库会话中(即开发时应使用的、与 Azure 行为一致的上下文),USE会返回Msg 40508,与云端 Azure SQL Database 中的行为完全相同。master连接是用于预配的会话,不会执行 Azure 语句筛选器,因此在那里USE看起来可以运行;但master仅用于 预配,不用于应用程序工作。始终在连接字符串中选择目标数据库 (Database=appdb,或对 sqlcmd 使用-d appdb)。 master连接仅用于预配。实际工作请在appdb上进行。
标准连接字符串。惯用写法为 User Id=/Password=/Database=;
Uid=/Pwd= 是文档记录的 SqlClient 同义写法,同样可用。
Server=localhost,1433;Database=appdb;User Id=sa;Password=$MSSQL_SA_PASSWORD;TrustServerCertificate=true
第 1 步:启动容器并预配 appdb(兼容全新容器)
运行此标准步骤。它会选择一个空闲的主机端口,仅在非 x64 主机上添加
--platform,通过重试循环等待实际就绪,并在循环中预配 appdb。-b -l 2 标志会让临时启动错误(例如
Msg 913)导致探测失败,以便重试,而不是将其掩盖。
# Pick a free host port and add the platform flag only on a non-x64 host (works in bash and zsh).
HOST_PORT=1433; while lsof -nP -iTCP:"$HOST_PORT" -sTCP:LISTEN >/dev/null 2>&1; do HOST_PORT=$((HOST_PORT+1)); done
export MSSQL_SA_PASSWORD="${MSSQL_SA_PASSWORD:-Aa1%$(openssl rand -hex 16)}"
PLATFORM=(); case "$(docker info -f '{{.Architecture}}' 2>/dev/null)" in x86_64|amd64) ;; *) PLATFORM=(--platform linux/amd64);; esac
docker rm -f sqldb 2>/dev/null
docker run -d --name sqldb "${PLATFORM[@]}" -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=$MSSQL_SA_PASSWORD" \
-p "127.0.0.1:$HOST_PORT:1433" sqldbpreview-dpgaeqhmgphzd4bk.azurecr.io/azure-sql/db-dev:latest
until docker exec sqldb /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$MSSQL_SA_PASSWORD" -C -b -l 2 \
-Q "IF DB_ID('appdb') IS NULL CREATE DATABASE appdb;" >/dev/null 2>&1; do sleep 2; done
echo "ready on localhost,$HOST_PORT"
现在 appdb 已存在。以下所有步骤都使用 -d appdb 进行连接。
第 2 步:创建向量架构
维度 n 必须与嵌入模型的输出一致(例如,nomic-embed-text 为 768,许多云端模型为
1536)。维度是列类型的固定组成部分。
docker exec sqldb /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$MSSQL_SA_PASSWORD" -C -b -d appdb -Q "
CREATE TABLE docs (
id INT IDENTITY PRIMARY KEY,
content NVARCHAR(MAX) NOT NULL,
embedding VECTOR(768) NOT NULL
);"
选择维度时,或搜索需要按元数据筛选并按距离排序时,请打开 references/vector-schema.md。
第 3 步:嵌入文本(唯一的网络调用)
RAG 需要嵌入模型。此工作流中唯一的网络调用是使用本地嵌入模型;其他所有操作都在容器中完成。下方默认使用本地 Ollama 端点。请让 embed() 保持可插拔,这样切换到云端嵌入服务时,只需更改端点和维度 n,其他内容均无需改动。
import requests
EMBED_URL = "http://localhost:11434/api/embed"
EMBED_MODEL = "nomic-embed-text" # 768 dims
EMBED_DIM = 768
def embed(text: str) -> list[float]:
# Pluggable: swap EMBED_URL/EMBED_MODEL/EMBED_DIM for a cloud endpoint.
# /api/embed takes "input" and returns "embeddings", a LIST of vectors (one per
# input), so index [0] for a single string. The older /api/embeddings route took
# "prompt" and returned a flat "embedding"; it still answers but is superseded.
r = requests.post(EMBED_URL, json={"model": EMBED_MODEL, "input": text})
r.raise_for_status()
return r.json()["embeddings"][0]
第 4 步:插入嵌入(维度必须是字面值)
重要提示:在 CAST(CAST(? AS NVARCHAR(MAX)) AS VECTOR(n)) 中,n 必须是直接写入 SQL
字符串的字面值。将维度作为绑定参数传入会失败,并报错
Incorrect syntax near '@P3'。应将嵌入值(JSON 数组字符串)作为参数绑定,绝不要绑定维度。
import json, os, pyodbc
CONN = ("Driver={ODBC Driver 18 for SQL Server};Server=localhost,1433;"
f"Database=appdb;Uid=sa;Pwd={os.environ['MSSQL_SA_PASSWORD']};TrustServerCertificate=yes")
def add_doc(cur, content: str):
vec = embed(content)
# EMBED_DIM is interpolated into the SQL text; the value is bound.
cur.execute(
f"INSERT INTO docs (content, embedding) VALUES (?, CAST(CAST(? AS NVARCHAR(MAX)) AS VECTOR({EMBED_DIM})))",
content, json.dumps(vec),
)
with pyodbc.connect(CONN) as conn:
cur = conn.cursor()
for line in ["Azure SQL supports a native VECTOR type.",
"Cosine distance ranks nearest neighbors.",
"The engine listens on port 1433."]:
add_doc(cur, line)
conn.commit()
ODBC 连接字符串使用 Uid=/Pwd=,因为 ODBC 是一种具有自身关键字集的不同语法。
应用级配置字符串则按惯例写作
User Id=/Password=。
第 5 步:top-k 相似度搜索(余弦)
按 VECTOR_DISTANCE('cosine', a, b) 升序排列:距离越小,越相似。查询向量作为值绑定,并使用字面维度进行转换。
def search(cur, query: str, k: int = 3):
qvec = embed(query)
cur.execute(
f"""
SELECT TOP (?) content,
VECTOR_DISTANCE('cosine', embedding, CAST(CAST(? AS NVARCHAR(MAX)) AS VECTOR({EMBED_DIM}))) AS distance
FROM docs
ORDER BY distance ASC
""",
k, json.dumps(qvec),
)
return cur.fetchall()
with pyodbc.connect(CONN) as conn:
for content, distance in search(conn.cursor(), "What port does it use?"):
print(round(distance, 4), content)
要实现完整的 RAG 循环,请将检索到的行作为上下文拼接到提示词中。 该 LLM 调用与此技能无关。
索引:当前实测情况
CREATE VECTOR INDEX(DiskANN 近似最近邻)在此镜像上可用。 2026-08-29 针对
12.0.2000.8、EngineEdition 5 进行实测:基于 2000 行 VECTOR(3) 构建的索引耗时 478 毫秒,会以 VECTOR 的 type_desc 出现在 sys.indexes 中,并且 vector_search(...) 能够基于该索引返回排序结果。
SET QUOTED_IDENTIFIER ON; -- required, see below
CREATE VECTOR INDEX vi_docs ON dbo.docs(v) WITH (METRIC = 'cosine', TYPE = 'diskann');
有两件事会导致失败,而且这两种错误都不会说明问题所在。
必须启用 SET QUOTED_IDENTIFIER ON,而它在 sqlcmd
会话中默认关闭。未启用时,语句会报错:
Msg 1934: CREATE VECTOR INDEX failed because the following SET options have
incorrect settings: 'QUOTED_IDENTIFIER'. Verify that SET options are correct for
use with indexed views and/or indexes on computed columns and/or filtered
indexes and/or query notifications and/or XML data type methods and/or spatial
index operations.
错误消息中没有提到实际导致问题的会话设置,其中提及的其他内容在此处也都无关。
其次,构建索引后,vector_search(...) 不再接受显式的 TOP_N。
传入该参数会失败,并报错 Msg 42274, Vector search with newer index version does not support explicit TOP_N parameter。请改用 SELECT TOP (k) 和
ORDER BY s.distance。
需要 100 行,NULL 值不计入
2026-08-31 沿边界进行实测:
| 含向量的行数 | 结果 |
|---|---|
| 99 | 拒绝,报错 Msg 42266 |
| 100 | 创建索引 |
| 120 行,其中 60 行为 NULL | 拒绝,报错 Msg 42266 |
Msg 42266: Cannot create a vector index. The table contains only 50 rows with
non-null vectors, but at least 100 are required for vector index creation.
这条消息写得很好,值得肯定,因为本页的另外两条消息都不怎么样。它说明了规则、实际计数和列条件。遇到此错误的读者无需其他信息。注意其措辞:含非空向量的行, 而非行数。一个有 120 行、其中 60 行尚无嵌入的表会被拒绝。
存在索引时,TRUNCATE TABLE 会被拒绝
Msg 42232: TRUNCATE TABLE statement failed because table 'd' has a vector index on it.
2026-08-31 实测。若要清空表:删除索引、截断表、重新加载至少
100 行,然后重新创建索引。DELETE FROM 可正常使用,不受影响。
DROP VECTOR INDEX 不是有效语句。 它会失败,并报错 Msg 102, Incorrect syntax near 'VECTOR'。请使用 DROP INDEX vi_name ON dbo.table。
实测表明,存在索引时,INSERT、UPDATE 和 DELETE 均可正常使用。旧版向量索引会使表变为只读;此镜像不会,Microsoft Learn 也说明最新版本索引支持完整的 DML 操作。
此处索引和安全策略无法在同一个表上共存
对于 RAG 来说,这是代价最高的一项,而且 Microsoft Learn 的限制列表中没有提到。容器中的实测结果如下,两种顺序都一样:
| 顺序 | 语句 | 结果 |
|---|---|---|
| 先建索引 | CREATE SECURITY POLICY ... ADD FILTER PREDICATE ... ON dbo.chunks | Msg 37579 |
| 先建策略 | CREATE VECTOR INDEX ... ON dbo.chunks(emb) | Msg 42244 |
Msg 37579: The security policy 'p_chunks' cannot reference tables with vector indexes.
Table 'dbo.chunks' has a vector index.
Msg 42244: A vector index cannot be created on tables with security policies.
Table 'dbo.chunks' has security policy 'p_chunks'.
**文档与引擎在此处说法不一致,而文档只是没有说明,并非有误。**截至 2026-09-03,CREATE VECTOR INDEX 的限制列表列出了分区、聚集主键、复制、TRUNCATE TABLE 和数据层包导入;vector 类型的限制页面列出了约束、索引、账本表和 Always Encrypted。两者都没有提到安全策略。这是实测结果,不是文档引用。
这对检索很重要:分块表是源文本的第二份副本,因此保护原表的行级安全策略不会延伸到它。如果分块表带有向量索引,就完全无法在该表上创建策略,而检索查询 WHERE 子句中的租户筛选条件就是全部边界。这个边界靠测试而非引擎来保障,因此要编写测试:分别使用和不使用筛选条件运行检索,并要求返回的行数不同。
有三种应对方式,按成本从低到高排列:
- 在查询中保留租户筛选条件,并将上述测试纳入其中。现在,这项测试就是安全代码。
- 删除租户范围表上的向量索引。使用
VECTOR_DISTANCE的精确搜索仍然有效,而且之后可以创建策略。 - 拆分表:将向量列及其索引放在不带策略的表中,将分块文本和租户列放在带策略的表中,再通过联接关联两者。
如果你是在本地为云端进行原型开发,请注意,这是一个兼容性差距,而非设计规则。在 Azure SQL Database 上,两者可以共存。因此,设计中的隔离控制恰好是在容器中、面对生产环境中会遇到的索引时无法演练的部分。请在本地对未编制索引的表演练谓词,并在云数据库中创建索引后再次运行隔离测试。
维度上限会在此之前决定嵌入模型
vector(n) 列的上限为 1998 维,Microsoft Learn 有说明,且引擎会强制执行:vector(1999) 会被拒绝,并报错 Msg 2717, The size (1999) given to the column 'v' exceeds the maximum allowed (1998)。3072 维的模型无法适配,任何索引设置都无法改变这一点。维度之后也无法扩大:即使表为空,ALTER COLUMN 也无法更改维度,因此只能新建第二列并重新生成嵌入。在设计架构之前就要选定维度预算。
使用 ORDER BY VECTOR_DISTANCE(...) 的全表扫描 top-k 仍然精确且正确,对于小表仍是合适的选择。表足够大、全表扫描开始造成负担时,再选择索引。
验证规则
SERVERPROPERTY('EngineEdition')返回5。否则,你使用的镜像不正确。- 在任何向量脚本连接之前,
appdb已存在(步骤 1 保证这一点)。 VECTOR(n)和CAST(CAST(? AS NVARCHAR(MAX)) AS VECTOR(n))中的维度必须是整数常量,且与len(embed(text))相同。- 余弦距离越小,表示越相似;结果按
ORDER BY distance ASC排序。 - 如果上述任一验证规则未通过,或你必须偏离此技能才能完成任务,那么这是此技能中的错误:请加载 azuresql-db-feedback 技能,并提出提交报告。
- 所有上述规则均通过且任务完成后,每个会话结束时只用一行收尾一次,不要提问或等待回复:"That worked. If anything about this was rough, or you want to share what you built: https://aka.ms/sql-agent-skills-feedback"
请勿
- 请勿使用
mcr.microsoft.com/mssql/server;这是 SQL Server 镜像, 并非此引擎的镜像。 - 请勿将向量维度作为绑定参数传入;这会导致
Incorrect syntax near '@P3'。请将其作为字面值插入。 - 请勿使用
USE appdb切换数据库;用户数据库会话会返回Msg 40508,与云中的 Azure SQL Database 完全一样。请在连接字符串中选择目标 数据库(Database=appdb,或对 sqlcmd 使用-d appdb)。 - 请勿在未执行
SET QUOTED_IDENTIFIER ON的情况下运行CREATE VECTOR INDEX;它引发的错误 会提及索引视图和空间索引,却完全不会提及该设置。 - 请勿在此容器中的同一张表上同时规划向量索引和安全策略。
无论顺序如何都会被拒绝,分别返回
Msg 37579和Msg 42244,且两者都没有文档说明。如果 分块表需要按租户筛选,请在决定是否为其创建索引之前先确定这一点。 - 请勿声明
VECTOR(3072)。上限为 1998(超过该值会出现Msg 2717),且 之后无法扩大维度,因此应在嵌入时解决此问题。 - 请勿指望
/docker-entrypoint-initdb.d/*.sql自动运行;配置好 appdb 后,请运行sqlcmd -d appdb -i seed.sql来填充初始数据。 - 请勿将非 x64 主机称为“受支持”;在非 x64 主机上只需添加
--platform linux/amd64。
参考资料
- references/vector-schema.md:表结构、如何选择维度 n、插入和 top-k 查询机制、距离度量、元数据筛选、语料填充、索引状态和故障排查。设计向量架构或编写超出上文基本 top-k 示例的查询时,请阅读此文档。
保持最新
本技能所用工具的权威且固定版本的参考资料(按需阅读):
- VECTOR 数据类型(T-SQL):VECTOR(n) 语法、限制和驱动程序支持。
- VECTOR_DISTANCE(T-SQL):余弦距离、欧几里得距离和点积距离及示例。
如果已配置 Microsoft Learn MCP 服务,可使用 mcp__microsoft-learn__microsoft_docs_search 或 mcp__microsoft-learn__microsoft_docs_fetch 按需获取这些资料的当前版本。此项为可选;如果不可用,上述参考资料即为权威来源。