为啥二进制中的 Sql Server 图像在字符串查询中导致问题但在参数化查询中有效

Posted

技术标签:

【中文标题】为啥二进制中的 Sql Server 图像在字符串查询中导致问题但在参数化查询中有效【英文标题】:Why Sql Server Image In Binary Causes Issue in string Query but works in Parameterized Query为什么二进制中的 Sql Server 图像在字符串查询中导致问题但在参数化查询中有效 【发布时间】:2014-04-25 12:48:57 【问题描述】:

我将图像保存在VarBinary 的表中及其工作。但问题是,如果我在 检索 时使用字符串查询保存图像,它会说参数无效,尽管图像二进制文件已保存在数据库中,我可以看到它。但如果我使用 parametrized 查询和 retrieve 图像,它会正确显示:

这是我的参数化查询代码:

     try
                    
                        byte[] byteImg = ImageToByteArray(pictureBox1.Image);
                        connection = con.getConnection();
                        if (connection != null)
                        
                            query = @"INSERT INTO [tblImages]
                               ([Image])
                         VALUES
                               (@image)";
                            connection.Open();
                            cmd = new SqlCommand(query, connection);
                            cmd.Parameters.AddWithValue("@image", byteImg);
                            cmd.ExecuteNonQuery();
                            MessageBox.Show("Saved");
                            connection.Close();
                            pictureBox1.Image = null;
                        
                    
                    catch (Exception ex)
                    
                        MessageBox.Show(ex.Message);
                    

使用参数化的数据库行视图:

这是我的字符串查询代码:

 try
                
                     byte[] byteImg = ImageToByteArray(pictureBox1.Image);
                    connection = con.getConnection();
                    if (connection != null)
                    
                        query = @"INSERT INTO [tblImages]
                           ([Image])
                     VALUES
                           (Convert(varbinary(MAX),'" + byteImg + "'))";
                        connection.Open();
                        cmd = new SqlCommand(query, connection);
                        cmd.ExecuteNonQuery();
                        MessageBox.Show("Saved");
                        connection.Close();
                        pictureBox1.Image = null;
                    
                
                catch
                

                

字节转换方法:

public byte[] ImageToByteArray(Image img)       
        
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            return ms.ToArray();
        

数据库行视图:

为什么会发生这种情况,为什么使用参数化查询二进制在行中不同,而使用字符串查询不同,这很奇怪。

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

你实际上可以这样做:

INSERT INTO [tblImages]  ([Image])
VALUES 0x5379......

要构建二进制字符串,请使用这样的代码(缓冲区是您的字节数组)

_sbScript.Append("0x");

for (int i = 0; i < buffer.Length; i++)

    _sbScript.Append(buffer[i].ToString("X2",System.Globalization.CultureInfo.InvariantCulture));

【讨论】:

十六进制格式:msdn.microsoft.com/en-us/library/…【参考方案2】:

在第二个数据快照 (0x53797374...) 的十六进制中,所有字节都拼出了类型名称(也许是“System.Byte[]”?我停止翻译...)。

0x53 - 'S'
0x79 - 'y'
0x73 - 's'
0x74 - 't'
0x65 - 'e'
0x6D - 'm'

当您使用 CONVERT(VARBINARY(MAX), '" + array + "')" 构建字符串时,将调用数组 ToString 方法,该方法在 System.Array 上没有很好地定义并返回类型的名称。然后你的 Sql 看起来像 INSERT INTO ... (CONVERT(VARBINARY(MAX), 'System.Byte[]') 并且会错误地插入到数据库中。

选择参数化选项肯定是更安全的方法(就安全性和潜在错误而言),但如果您想将其作为 SQL 字符串执行,您将需要构建一个实际字节的字符串,如 ErikEJ 的回答所示。

【讨论】:

【参考方案3】:

您在字符串查询代码中有不同的 INSERT 语句。

参数化查询代码为:

query = @"INSERT INTO [tblImages]
                 ([Image])
          VALUES (@image)";

而字符串查询代码为:

query = @"INSERT INTO [tblImages]
                 ([Image])
          VALUES (Convert(varbinary(MAX),'" + byteImg + "'))";

删除CONVERT 应该会使两个语句以相同的方式插入。

【讨论】:

以上是关于为啥二进制中的 Sql Server 图像在字符串查询中导致问题但在参数化查询中有效的主要内容,如果未能解决你的问题,请参考以下文章

帮助从 SQL Server 读取二进制图像数据到 PHP

如何在 R 中将图像上传到 SQL Server

为啥oracle数据库链接不显示来自sql server的图像类型的列

SQL Server文本和图像函数

SQL Server字符串或二进制数据将被截断

在 C# 中将十六进制值从 SQL Server 转换为日期时间