关于 azuresql-db-local-to-cloud
指导开发者先使用本地 Azure SQL Database 容器开发和测试,再部署到云端 Azure SQL Database。通过切换 SQL_CONNECTION_STRING,在不改应用代码的情况下切换环境,并区分本地验证结果与云端指引。
主要功能
- 01不同环境共用一个连接字符串变量
- 02配置本地 SQL 身份验证和云端 Entra 身份验证
- 03保持本地与云端的查询和架构一致
- 04应用连接前创建 appdb
- 05说明本地实测范围与云端指引
适用场景
- 01针对本地容器开发应用
- 02将部署从本地 SQL 切换到 Azure SQL Database
- 03配置本地 SA 与云端 Entra 身份验证
- 04判断本地到云端兼容性中哪些部分经过测试
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ microsoft/ azure-sql-database-container --skill azuresql-db-local-to-cloud安装后在 Claude Code 中输入/azuresql-db-local-to-cloud确认已加载。
附带文件references/auth-local-vs-cloud.mdskill.spec.jsonc
详细介绍
从 Azure SQL Database 容器到 Azure SQL Database:代码不变,从本地到云端
针对本地容器进行构建和测试,然后将同一份应用程序代码部署到云端的 Azure SQL Database。只需更改连接字符串,其他一概不变。
这是因为本地容器运行的是 Azure SQL Database 引擎,而不是 SQL Server 映像。SELECT SERVERPROPERTY('EngineEdition') 返回 5,SERVERPROPERTY('Edition') 返回 'SQL Azure',与云端相同。因此,代码所依赖的 SQL 功能在两处完全一致。
已于 2026-09-05 针对容器映像
sqldbpreview-dpgaeqhmgphzd4bk.azurecr.io/azure-sql/db-dev:latest 进行验证,报告的 EngineEdition
为 5,Edition 为 SQL Azure,版本为 12.0.2000.8。此技能所包含的六项可执行检查均已在容器上通过:引擎标识、USE 对应的 Msg 40508、BACKUP 和 RESTORE 对应的 Msg 40510、带参数且包含 OUTPUT inserted.id 的插入操作、单数据库模型,以及位于 /opt/mssql-tools18/bin/sqlcmd 的 sqlcmd。此次运行仅测量了容器。云端部分的兼容性声明,以及 Microsoft Entra ID 和托管标识的相关设置,均未在此次运行中测试,因此在宣布就绪前,请先对照真实的 Azure SQL Database 验证一次。
唯一规则
本地与云端之间不得更改应用程序代码。 应用程序从单个环境变量 SQL_CONNECTION_STRING 读取连接字符串。本地开发时将其设为容器;云端部署时将其设为 Azure SQL 服务器。同一组二进制文件、同一组查询、同一套架构。
如果你发现自己正在修改查询、驱动程序或架构,只为“让它在 Azure 上运行”,请停下:这是一个错误。唯一合理的差异是连接字符串(以及与之相应的身份验证方法)。
单个环境变量,两种取值
统一使用 SQL_CONNECTION_STRING。项目风格规定关键字写作
User Id= / Password= / Database=,以确保所有示例一致。Uid= 和 Pwd= 是文档记录的 SqlClient 同义写法,也可以使用。ODBC 连接字符串采用单独的语法,并使用 Uid= / Pwd= 作为其关键字。
本地(容器,SA 身份验证):
Server=localhost,1433;Database=appdb;User Id=sa;Password=$MSSQL_SA_PASSWORD;TrustServerCertificate=true
云端(Azure SQL Database,Microsoft Entra 身份验证):
Server=your-server.database.windows.net,1433;Database=appdb;Authentication=Active Directory Default;Encrypt=true
注意保持不变的部分:Database=appdb、表名和参数化 SQL。只有 Server、身份验证字段和 TLS 设置会变化。
本地 SA 身份验证与云端 Entra 身份验证(原因,不只是方法)
本地:容器使用环境变量 MSSQL_SA_PASSWORD 设置一个引导登录名 sa。笔记本电脑上的容器前面不需要身份提供方,因此通过受信任的自签名证书进行密码身份验证(TrustServerCertificate=true)是务实的本地默认方案。
容器也支持 Microsoft Entra ID 身份验证(使用 MSSQL_AAD_* 变量和证书挂载进行配置;请参阅
azuresql-db-container 技能中的 references/entra-auth.md)。如果你希望本地与云端更接近,可以使用此方案。大多数从本地到云端的流程仍然会先在本地使用 SQL 身份验证,再只更改连接字符串,在云端切换到 Entra 身份验证。
云端:Azure SQL Database 位于 Microsoft Entra ID 之后。应用程序不必发送密码,而是使用其 Entra 身份提供令牌(生产环境中使用托管标识;在本地连接云端时使用开发者登录身份)。驱动程序会获取令牌;你无需在连接字符串中放入机密信息。TLS 是真实且强制启用的,因此请使用 Encrypt=true,并删除 TrustServerCertificate。
应用程序代码无需为此设置分支。驱动程序会读取连接字符串中的 Authentication= 关键字(或确认该关键字不存在),并采取正确的操作。这正是此方案的核心:身份验证属于配置,而非代码。
设置云端时,请打开 references/auth-local-vs-cloud.md,其中包含令牌流程和各技术栈的身份验证设置。
本地容器的最少必要事实
只需了解这些内容,即可在全新容器中运行示例。完整详情请参阅 azuresql-db-container skill。
- 映像:
sqldbpreview-dpgaeqhmgphzd4bk.azurecr.io/azure-sql/db-dev:latest(x64,linux/amd64)。私有预览注册表:先使用提供给私有预览参与者的共享只读凭据运行docker login sqldbpreview-dpgaeqhmgphzd4bk.azurecr.io(请在 https://aka.ms/sqldbcontainerpreview-signup 注册获取;凭据可能会轮换)。私有预览期间,注册表和标签均为临时设置。 - 在非 x64 主机上,添加
--platform linux/amd64。 - 必需环境变量:
ACCEPT_EULA=Y和复杂的MSSQL_SA_PASSWORD(至少 8 个字符,包含大写字母、小写字母、数字和符号)。引擎监听 1433 端口。 - 引擎不会自动创建数据库。 连接到
master 后,必须先执行
CREATE DATABASE appdb,才能使用Database=appdb连接。master连接仅用于预配;实际工作应在appdb上进行。 - 所有会话中的
BACKUP和RESTORE都会被拒绝并返回Msg 40510;本地行为与云端完全一致。备份容器并将文件还原到 Azure SQL Database 并非升级路径;请使用 SqlPackage 迁移架构和数据(参见 azuresql-db-import skill)。 - 跨数据库查询在本地会被拒绝,与云端一致。因此,如果应用将所有对象都保存在一个用户数据库中,它在本地通过的原因与它在该服务上通过的原因相同。
IDENTITY列在这里的行为与云端一致。以下示例在两者中均原样使用INT IDENTITY PRIMARY KEY;通常有人会无谓地建议重写的地方之一就是这里。- 避免使用
USE切换数据库。在用户数据库会话中(即开发时与 Azure 行为一致的上下文),USE会返回Msg 40508,与云端的 Azure SQL Database 完全一致。master连接是预配会话,不会强制执行 Azure 语句筛选器,因此在其中USE看似有效;但master仅用于预配,不用于应用工作。请始终在连接字符串中选择目标数据库(Database=appdb,或对 sqlcmd 使用-d appdb)。
启动容器并预配 appdb(标准方案)
运行一次即可。此方案会选择一个空闲主机端口,仅在需要时添加 --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
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"
然后使用循环最终选定的 HOST_PORT,将应用指向该容器:
export SQL_CONNECTION_STRING="Server=localhost,$HOST_PORT;Database=appdb;User Id=sa;Password=${MSSQL_SA_PASSWORD};TrustServerCertificate=true"
稍后要连接云端时,只需更改此变量;不要修改应用。
已测量的内容与指导性内容
请如实告诉用户,这项 skill 的哪一部分有证据支持。
本地部分经过了实测。 此 skill 中的每项探测都针对该容器运行,且覆盖了支持一致性声明的内容:引擎报告 EngineEdition 5 和 Edition SQL Azure,USE 返回 Msg 40508,BACKUP 返回 Msg 40510,跨数据库查询会被拒绝,并且以下示例运行的精确 CRUD 批处理会返回示例读取的标识值。
云端部分属于指导。 此仓库从未针对逻辑服务器运行过任何探测,因此云端连接字符串、Microsoft Entra 令牌流程和部署清单均依据产品文档编写,而非来自实际运行。这是有意为之,并非有待填补的空白:该容器的全部意义在于本地开发无需云数据库,因此要求使用云数据库来验证此 skill 将与其初衷相悖。提到云端时,请说“这是文档所述的形式”,而不是“这已经过验证”。
证明:相同代码,两种技术栈
每个示例都假设 appdb 已存在(由上面的操作步骤创建),并从环境中读取
SQL_CONNECTION_STRING。它会在需要时创建表,并运行一个参数化 CRUD 事务。先使用本地连接字符串运行一次,
再使用云端连接字符串运行一次:代码相同,结果相同。本地运行有此技能的证据支持;云端运行则是预期会得到的结果。
Node (mssql)
// app.mjs -> node app.mjs (ESM: use the .mjs extension, or set "type":"module" in package.json)
import sql from 'mssql';
const pool = await sql.connect(process.env.SQL_CONNECTION_STRING);
const tx = new sql.Transaction(pool);
await tx.begin();
try {
const r = new sql.Request(tx);
await r.query(`IF OBJECT_ID('dbo.todo') IS NULL
CREATE TABLE dbo.todo (id INT IDENTITY PRIMARY KEY, title NVARCHAR(200), done BIT);`);
// CREATE
const ins = await new sql.Request(tx)
.input('title', sql.NVarChar, 'ship local-to-cloud')
.query('INSERT INTO dbo.todo(title, done) OUTPUT inserted.id VALUES (@title, 0);');
const id = ins.recordset[0].id;
// UPDATE
await new sql.Request(tx)
.input('id', sql.Int, id)
.query('UPDATE dbo.todo SET done = 1 WHERE id = @id;');
// READ
const read = await new sql.Request(tx)
.input('id', sql.Int, id)
.query('SELECT id, title, done FROM dbo.todo WHERE id = @id;');
console.log(read.recordset[0]);
await tx.commit();
} catch (e) { await tx.rollback(); throw e; }
await pool.close();
.NET (Microsoft.Data.SqlClient)
// Program.cs -> dotnet run (uses Microsoft.Data.SqlClient)
using Microsoft.Data.SqlClient;
var cs = Environment.GetEnvironmentVariable("SQL_CONNECTION_STRING");
using var conn = new SqlConnection(cs);
conn.Open();
using var tx = conn.BeginTransaction();
try {
new SqlCommand(@"IF OBJECT_ID('dbo.todo') IS NULL
CREATE TABLE dbo.todo (id INT IDENTITY PRIMARY KEY, title NVARCHAR(200), done BIT);",
conn, tx).ExecuteNonQuery();
// CREATE
var ins = new SqlCommand(
"INSERT INTO dbo.todo(title, done) OUTPUT inserted.id VALUES (@title, 0);", conn, tx);
ins.Parameters.AddWithValue("@title", "ship local-to-cloud");
int id = (int)ins.ExecuteScalar();
// UPDATE
var upd = new SqlCommand("UPDATE dbo.todo SET done = 1 WHERE id = @id;", conn, tx);
upd.Parameters.AddWithValue("@id", id);
upd.ExecuteNonQuery();
// READ
var sel = new SqlCommand("SELECT id, title, done FROM dbo.todo WHERE id = @id;", conn, tx);
sel.Parameters.AddWithValue("@id", id);
using var r = sel.ExecuteReader();
while (r.Read()) Console.WriteLine($"{r["id"]} {r["title"]} {r["done"]}");
tx.Commit();
} catch { tx.Rollback(); throw; }
Python (pyodbc) 参考示例
如果你的技术栈是 Python,或者你已准备好部署,请打开 references/auth-local-vs-cloud.md,因为第三种技术栈的示例和部署检查清单位于该文件中,而非此处。
验证规则
- 应用连接前,
appdb必须已存在。先在master上创建它(操作步骤中已包含此步骤)。引擎不会自动创建它。 - 应用只读取一个连接变量:
SQL_CONNECTION_STRING。 - 本地连接字符串使用 SA 身份验证 +
TrustServerCertificate=true;云端连接字符串使用Authentication=Active Directory Default+Encrypt=true。 - .NET 风格的连接字符串按项目惯例使用关键字
User Id=/Password=/Database=。Uid=/Pwd=是有效的同义写法,因此不算错误。ODBC 连接字符串保留 ODBC 自己的Uid=/Pwd=。 - 切换环境时只需更改连接字符串。本地和云端之间的应用代码差异为零行。
- 上述所有规则中,云端部分属于指导内容,而非此技能实际运行过的内容。不要向用户声称已验证。
- 如果上述验证规则有任何一项未通过,或者你为了完成任务而不得不偏离此技能,这就是此技能中的错误:加载 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"
请勿
- 请勿使用 SQL Server 映像
mcr.microsoft.com/mssql/server。如果你正准备使用它,请停下并改用上面的映像;这是 Azure SQL 引擎。 - 请勿在
master上创建appdb之前连接到Database=appdb。 - 请勿使用
USE appdb切换数据库;用户数据库会话会返回Msg 40508,与云端 Azure SQL Database 的行为完全相同。请在连接字符串中选择目标数据库(Database=appdb,或在 sqlcmd 中使用-d appdb)。 - 请勿在云端连接字符串中放入密码或机密;请使用 Entra 身份验证,并让驱动程序获取令牌。
- 请勿按环境分支编写应用逻辑;将身份验证保留在配置中。
- 请勿将非 x64 主机称为“受支持”;在非 x64 主机上,只需添加
--platform linux/amd64。
参考资料
- references/auth-local-vs-cloud.md:说明本地 SA 身份验证与云端 Microsoft Entra 身份验证为何不同、令牌流程、各技术栈的身份验证设置、Python (pyodbc) 示例以及部署检查清单。在配置云端连接字符串或将应用部署到 Azure 时阅读。
保持最新
此技能所用工具的权威版本固定参考资料(按需阅读):
- 连接并查询 Azure SQL Database:云服务的各语言快速入门、连接信息、TLS 和驱动程序。
- SqlConnection 连接字符串关键字:完整的连接字符串关键字表。
如果已配置 Microsoft Learn MCP 服务,请使用 mcp__microsoft-learn__microsoft_docs_search 或 mcp__microsoft-learn__microsoft_docs_fetch 按需获取这些资料的当前版本。该服务为可选项;不可用时,上述参考资料具有权威性。