【问题标题】:Inserting String data into Varbinary User-Defined Data Type Column SQL Server .NET将字符串数据插入 Varbinary 用户定义的数据类型列 SQL Server .NET
【发布时间】:2014-12-08 07:33:30
【问题描述】:

我需要将记录插入到包含 varbinary 和 image 列的 SQL 表中。

如何获得 0x00120A011EFD89F94DDA363BA64F57441DE9(所有记录都一样)

进入这个

BLOB_TYPE (MY_UDDT(varbinary(18))?

这是我目前所拥有的,除了 SqlDbType.Udt 参数定义之外,一切都非常简单。使用此代码,我收到错误消息“指定的类型未在目标服务器上注册。System.Byte []”,我可以说 100% 的“用户定义的数据类型”存在于服务器上。我从 sys.types 中查询了 select *,它返回了类型。

定义:CREATE TYPE [dbo].[MY_UDDT] FROM varbinary NOT NULL

        sql = "INSERT INTO dbo.BLOBS (BLOB_TYPE) VALUES (@BLOB_TYPE);"
        cmd = New SqlCommand(sql, conn)
        Dim parameter As New SqlParameter("@BLOB_TYPE", SqlDbType.Udt)
        With parameter
            .SqlDbType = SqlDbType.Udt
            .UdtTypeName = "dbo.MY_UDDT"
            .Value = blobType
        End With
        cmd.Parameters.Add(parameter)
        cmd.ExecuteNonQuery()

Public ReadOnly Property blobType As Byte()
    Get
        Dim Str As String = "0x00620A011EFD89F94DDA863BA64F57441DE9"
        Dim bytes As Byte() = New Byte(Str.Length * 2 - 1) {}
        System.Buffer.BlockCopy(Str.ToCharArray(), 0, bytes, 0, bytes.Length)
        Return bytes
    End Get
End Property

【问题讨论】:

    标签: sql-server vb.net sqlclr sqlcommand user-defined-types


    【解决方案1】:

    这里有几件事被误解了:

    • 用户定义的数据类型 (UDDT) 和用户定义的类型 (UDT) 之间有很大的不同,尽管由于名称相似,人们会感到困惑是可以理解的。
      • 您通过CREATE TYPE 创建的是UDDT,而不是UDT。这是一个仅限 T-SQL 的构造。
      • 未来注意事项:指定可变长度数据类型时,请务必指定长度: VARBINARY(18) 而不是 VARBINARY
      • UDT 是一个 SQLCLR 构造。以下是 MSDN 上以这种方式使用 UDT 的示例:
        http://msdn.microsoft.com/library/ms131080.aspx
    • 这里不需要任何花哨的东西。你只需要设置:
      • SqlDbType = SqlDbType.VarBinary
      • Size = 18
    • 您的blobType 函数未发送您期望的字符串的十六进制表示。它正在发送字符串“0x00620A011EFD89F94DDA863BA64F57441DE9”的每个字符的十六进制值。意思是,“0”的十六进制值(即 48 或 0x30),然后是“x”的十六进制值(即 120 或 0x78),以此类推所有 38 个字符。

      您需要在“0x”之后取每组 2 个字符(即“00”然后是“62”然后是“0A”等等),将它们转换为实际字节,然后发送数组。

      如果您在 VB 中将值作为字符串并使用 SQL Server 2008 或更高版本,则可以将字符串传入并让 SQL Server 为您转换。您只需将 INSERT 语句修改为: INSERT INTO dbo.BLOBS (BLOB_TYPE) VALUES (CONVERT(VARBINARY(18), @BLOB_TYPE, 1));

      CONVERT 函数使用“1”样式(意思是:二进制的字符串表示,以“0x”开头)可以解决问题。例如:

      SELECT CONVERT(VARBINARY(18), '0x00620A011EFD89F94DDA863BA64F57441DE9', 1)

      当然,那你需要把SqlParameter属性改成:

      • SqlDbType = SqlDbType.VarChar
      • Size = 38

    【讨论】:

      【解决方案2】:

      问题在于参数值是一个字节数组,而不是您声称要传入的 UDT 的实例,而且System.Byte[] 不出所料地不是注册的 UDT。

      这令人困惑,但 .NET 端的“UDT”仅用于在程序集 (CREATE TYPE ... EXTERNAL NAME) 中创建的 UDT,而不用于基于 SQL Server 类型(在联机丛书中称为“别名数据类型”)的 UDT )。要传递这些,不要SqlDbType 设置为Udt,而只需传入底层基本类型的值。基本上,这些类型只在数据库端有用,以确保一致性。

      此外,您错误地构造了 blob - 您需要将十六进制字符串转换为字节,而不是组成十六进制字符串的字符。如果它真的是一个常数,你可以这样声明它。所以:

      cmd.Parameters.AddWithValue("@BLOB_TYPE", New Byte() { &H00, &H62, &H0A, &H01, &H1E, &HFD, &H89, &HF9, &H4D, &HDA, &H86, &H3B, &HA6, &H4F, &H57, &H44, &H1D, &HE9 })
      

      应该做的伎俩。

      【讨论】:

        【解决方案3】:

        SqlDbType.Udt 用于 SQLCLR 类型。在这种情况下,您有一个 varbinary 列,因此请指定 SqlDbType.VarBinary 以及最大大小 (18)。对于值,传递包含原始二进制值的字节数组。

        您提到了一个 18 字节的 varbinary 数据类型,但数据看起来要长得多。如果您的意图是将十六进制表示法的字符串转换为 18 字节的二进制值,那么这与此处提出的问题不同。如果您需要帮助,我建议您发布另一个问题。

        【讨论】:

        • 除非我遗漏了什么,否则字符串长度为 38 个字符(包括“0x”前缀),当从函数返回时,它是一个 76 字节的字节数组,因为字符串是 Unicode。我怀疑这不是你的意图。
        • 糟糕!你是对的,当然。我自动没有考虑“0x”。我的意思是暗示 OP 的示例强烈似乎是值的十六进制字符串表示。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-22
        • 2011-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多