矢量数据类型

适用于: SQL Server 2025 (17.x)Azure SQL 数据库Azure SQL 托管实例Microsoft Fabric 中的 SQL 数据库

向量数据类型存储了针对相似性搜索和机器学习应用等操作优化的向量数据。 矢量以优化的二进制格式存储,但为了方便起见,以 JSON 数组的形式公开。 矢量的每个元素都以单精度(4 字节)浮点值的形式存储。

为了为开发人员提供熟悉的体验,将创建 矢量 数据类型并将其显示为 JSON 数组。 例如,具有三个维度的向量可以表示为 '[0.1, 2, 30]'。 vector 类型与 char、nchar、varchar、nvarchar 和 json 类型之间的转换可以是隐式的,也可以是显式的,并且可以双向进行。 不允许在 向量 和所有其他数据类型之间转换。 只有当两个vector值的维度和基类型(float32或float16)相同时,才允许它们之间进行转换;否则,会出现错误42204或错误42238。

当你把字符串或 json 值转换成 向量时,这个值必须是一个由数字组成的 JSON 数组。 元素数必须等于矢量维数;否则,将发生 42204 错误。 其他值会导致错误 13670。 数组前后空白部分被忽略。

当你将 向量 转换为字符串类型时,结果会使用科学记号,例如 [1.0000000e+000,2.5000000e+000,-3.0000000e+000]。 当你把 向量 转换成 json 时,结果会使用十进制表示法,比如 [1.0000000000,2.5000000000,-3.0000000000]。 如果目标长度过短,则会出现错误42211。 该值未被截断。

向量 的优先级低于字符串类型。 在 UNION、 CASE、 COALESCE、 以及其他将 向量 与字符串类型结合的表达式中,结果就是字符串类型。

若要详细了解如何使用矢量数据,请参阅:

示例语法

矢量类型的用法语法与表中所有其他 SQL Server 数据类型相似。

column_name VECTOR ( { <dimensions> } ) [ NOT NULL | NULL ]

默认情况下,基础类型是 float32。 要使用 半精度,可以明确指定 float16 。

column_name VECTOR ( <dimensions> [ , <base_type> ] ) [ NOT NULL | NULL ]

Dimensions

矢量必须至少有一个维度。 最大维数取决于向量基类型:

  • float32 支持最多 1,998 个维度。
  • float16 支持最多 3,996 个维度。

功能可用性

矢量数据类型适用于所有数据库兼容性级别。 如果你没有指定基类型,向量就用 float32。

矢量功能可在配置为“始终最新”策略的 Azure SQL 托管实例中使用。

半精度 16 位浮点向量

  • 半精度(float16)向量通常可在 Azure SQL 数据库、Azure SQL 托管实例 以及 Microsoft Fabric 中的 SQL 数据库中获得。 无需预览配置。

  • 在 SQL Server 2025(17.x)中,预览版中提供了半精度(float16)向量。 要在 SQL Server 2025 中使用 float16,必须启用PREVIEW_FEATURES数据库作用域配置选项。 更多信息请参见“启用 SQL Server 2025 中的预览功能”。

关于半精度向量的更多信息,请参见 向量数据类型中的半精度浮点支持。

启用 SQL Server 2025 中的预览功能

对于 SQL Server 2025 中的某些预览功能,您必须启用PREVIEW_FEATURES数据库范围配置选项。

ALTER DATABASE SCOPED CONFIGURATION
SET PREVIEW_FEATURES = ON;
GO

更多信息请参见 PREVIEW_FEATURES。

Examples

A. 列定义

在语句中的CREATE TABLE列定义中使用向量类型。 例如:

以下示例创建了一个带有矢量列的表,并向其中插入数据。

在表中定义 向量 列时,可以使用默认的基础类型 float32,或者使用 float16 进行半精度存储。

CREATE TABLE dbo.vectors
(
    id INT PRIMARY KEY,
    v VECTOR(3) NOT NULL -- Uses default base type (**float32**)
);

CREATE TABLE dbo.vectors_fp16
(
    id INT PRIMARY KEY,
    v VECTOR(3, float16) -- Uses float16 for reduced storage and precision
);

INSERT INTO dbo.vectors
(
    id,
    v
)
VALUES (1, '[0.1, 2, 30]'),
       (2, '[-100.2, 0.123, 9.876]'),
       (3, JSON_ARRAY(1.0, 2.0, 3.0)); -- Using JSON_ARRAY to create a vector

SELECT *
FROM dbo.vectors;

B. 在变量中的使用

以下示例通过使用新的 向量 数据类型声明向量,并通过函数 VECTOR_DISTANCE 计算距离。

使用带变量的 向量 类型:

DECLARE @v AS VECTOR(3) = '[0.1, 2, 30]';

SELECT @v;
GO

DECLARE @v AS VECTOR(3, float16) = '[0.1, 2, 30]';

SELECT @v;

C. 在存储过程或函数中的使用

你可以在存储过程或函数中使用 向量 数据类型作为参数。 例如:

CREATE PROCEDURE dbo.SampleStoredProcedure
(
    @V VECTOR(3),
    @V2 VECTOR(3) OUTPUT
)
AS
BEGIN
    SELECT @V;
    SET @V2 = @V;
END

Conversions

  • 你不能用 向量 类型和 sql_variant 类型,也不能把它分配给 sql_variant 变量或列。 此限制类似于 varchar(max)、 varbinary(max)、 nvarchar(max)、 xml、 json 和基于 CLR 的数据类型。

Compatibility

TDS 协议的增强功能

SQL Server 以优化的二进制格式存储矢量,但为了方便起见,将它们公开为 JSON 数组。

支持的 驱动程序使用 TDS 协议的增强功能以二进制格式更有效地传输矢量数据,并将其作为本机向量类型呈现给应用程序。 此方法可减少有效负载大小,消除 JSON 分析的开销,并保留完整的浮点精度。 因此,在 AI 和机器学习方案中处理高维矢量时,它提高了性能和准确性。

本机驱动程序支持

使用 TDS 版本 7.4 或更高版本 和更新的驱动程序的应用程序可以本机读取、写入、流式传输和大容量复制向量数据。

这些功能需要以下驱动程序的版本。 确保使用正确的版本来启用本机向量支持。

  • Microsoft.Data.SqlClient:版本 6.1.0 引入了类型 SqlVector ,扩展 System.Data.SqlDbTypes。
  • Microsoft JDBC Driver for SQL Server:版本 13.1.0 预览版 引入了 microsoft.sql.Types.VECTOR 类型和 microsoft.sql.Vector 类。

Note

Microsoft JDBC Driver 13.4 for SQL Server 和 Microsoft ODBC Driver 18.7.1 for SQL Server 支持原生二进制传输 float16 向量。 这些驱动程序使用原生线格式进行半精度矢量值的序列化和反序列化,从而相比 JSON 表示方式减少了网络有效载荷。 使用这些驱动版本或更高版本,以支持原生 float16 传输。 不支持原生 float16 传输的驱动程序仍可继续使用以 varchar(max) JSON 数组表示的向量。

Note

对于不支持更新的 TDS 协议的客户端,SQL Server 将继续将矢量数据公开为 varchar(max) 类型,以确保向后兼容。 客户端应用程序可以使用矢量数据,就像它是 JSON 数组一样。 SQL 数据库引擎自动将矢量转换为 JSON 数组并从 JSON 数组转换回来,这使得新类型对客户端而言是透明的。 因此,驱动程序和所有语言都自动与新类型兼容。

可以立即开始使用新的 向量 类型。 以下示例显示了不同的语言和驱动程序配置。

Important

需要 Microsoft.Data.SqlClient 6.1.0 或更高版本以支持原生向量。

using Microsoft.Data;
using Microsoft.Data.SqlClient;
using Microsoft.Data.SqlTypes;

namespace VectorSampleApp
{
    class Program
    {
        // Set your environment variable or fallback to local server
        private static readonly string connectionString =
            Environment.GetEnvironmentVariable("CONNECTION_STR")
            ?? "Server=tcp:localhost,1433;Database=Demo2;Integrated Security=True;TrustServerCertificate=True";

        private const int VectorDimensions = 3;
        private const string TableName = "dbo.Vectors";

        static void Main()
        {
            using var connection = new SqlConnection(connectionString);
            connection.Open();
            SetupTables(connection, TableName, VectorDimensions);
            InsertVectorData(connection, TableName);
            ReadVectorData(connection, TableName);
        }

        private static void SetupTables(SqlConnection connection, string tableName, int vectorDimensionCount)
        {
            using var command = connection.CreateCommand();

            command.CommandText = $@"
                IF OBJECT_ID('{tableName}', 'U') IS NOT NULL DROP TABLE {tableName};
                IF OBJECT_ID('{tableName}Copy', 'U') IS NOT NULL DROP TABLE {tableName}Copy;";
            command.ExecuteNonQuery();

            command.CommandText = $@"
                CREATE TABLE {tableName} (
                    Id INT IDENTITY(1,1) PRIMARY KEY,
                    VectorData VECTOR({vectorDimensionCount})
                );

                CREATE TABLE {tableName}Copy (
                    Id INT IDENTITY(1,1) PRIMARY KEY,
                    VectorData VECTOR({vectorDimensionCount})
                );";
            command.ExecuteNonQuery();
        }

        private static void InsertVectorData(SqlConnection connection, string tableName)
        {
            using var command = new SqlCommand($"INSERT INTO {tableName} (VectorData) VALUES (@VectorData)", connection);
            var param = command.Parameters.Add("@VectorData", SqlDbTypeExtensions.Vector);

            // Insert null using DBNull.Value
            param.Value = DBNull.Value;
            command.ExecuteNonQuery();

            // Insert non-null vector
            param.Value = new SqlVector<float>(new float[] { 3.14159f, 1.61803f, 1.41421f });
            command.ExecuteNonQuery();

            // Insert typed null vector
            param.Value = SqlVector<float>.CreateNull(VectorDimensions);
            command.ExecuteNonQuery();

            // Prepare once and reuse for loop
            command.Prepare();
            for (int i = 0; i < 10; i++)
            {
                param.Value = new SqlVector<float>(new float[]
                {
                    i + 0.1f,
                    i + 0.2f,
                    i + 0.3f
                });
                command.ExecuteNonQuery();
            }
        }

        private static void ReadVectorData(SqlConnection connection, string tableName)
        {
            using var command = new SqlCommand($"SELECT VectorData FROM {tableName}", connection);
            using var reader = command.ExecuteReader();

            while (reader.Read())
            {
                var sqlVector = reader.GetSqlVector<float>(0);

                Console.WriteLine($"Type: {sqlVector.GetType()}, IsNull: {sqlVector.IsNull}, Length: {sqlVector.Length}");

                if (!sqlVector.IsNull)
                {
                    float[] values = sqlVector.Memory.ToArray();
                    Console.WriteLine("VectorData: " + string.Join(", ", values));
                }
                else
                {
                    Console.WriteLine("VectorData: NULL");
                }
            }
        }
    }
}

Note

如果你不用最新的 .NET 驱动,你仍然可以通过用 JsonSerializer 类将向量数据序列化和反序列化成 JSON 字符串来处理。 这种方法可确保与 SQL Server 为旧版客户端提供的向量的 varchar(max) 表示形式兼容。

using Microsoft.Data.SqlClient;
using Dapper;
using DotNetEnv;
using System.Text.Json;

namespace DotNetSqlClient;

class Program
{
    static void Main(string[] args)
    {
        Env.Load();

        var v1 = new float[] { 1.0f, 2.0f, 3.0f };

        using var conn = new SqlConnection(Env.GetString("MSSQL"));
        conn.Execute("INSERT INTO dbo.vectors VALUES(100, @v)", param: new {@v = JsonSerializer.Serialize(v1)});

        var r = conn.ExecuteScalar<string>("SELECT v FROM dbo.vectors") ?? "[]";
        var v2 = JsonSerializer.Deserialize<float[]>(r);
        Console.WriteLine(JsonSerializer.Serialize(v2));
    }
}

Tools

以下工具支持 向量 数据类型:

Limitations

矢量类型具有以下限制:

Tables

  • 列级约束不受支持,NULL 和 NOT NULL 约束除外。

    • DEFAULT和CHECK的约束不被支持在矢量列。

    • PRIMARY KEY列不支持键约束,例如 FOREIGN KEY 或 。 相等性、唯一性、使用向量列作为键联接,排序顺序不适用于 矢量 数据类型。

    • 矢量没有唯一性的概念,因此唯一约束不适用。

    • 检查向量中的值范围并不适用。

  • 矢量不支持比较、加法、减法、乘法、除法、串联或任何其他数学、逻辑和复合赋值运算符。

  • 你不能在内存优化表中使用 矢量 列。

Indexes

  • 你不能在 向量 列上使用B树索引或列存储索引。 不过,你可以在索引定义中将 vector 列作为包含列。
  • 向量索引在 向量列上创建一个近似索引,以提升最近邻搜索的性能。 想了解更多向量索引和向量搜索的工作原理,以及精确搜索和近似搜索的区别,请参见SQL 数据库引擎中的向量搜索和向量索引。

表架构元数据

  • sp_describe_first_result_set系统存储过程无法正确返回矢量数据类型。 因此,许多数据访问客户端和驱动程序会看到 varchar 或 nvarchar 数据类型。

账本表

  • 如果数据库中存在带有 sp_verify_database_ledger 列的表,存储过程 会报错。

用户定义类型

  • 你不能使用 CREATE TYPE 为 vector 类型创建别名。 这一限制类似于 XML 和 JSON 数据类型的行为。

始终加密 (Always Encrypted)

  • vector 类型不受 Always Encrypted 功能支持。

已知问题

  • 数据掩码当前在 Azure 门户中以 varbinary 数据类型的形式显示矢量数据。