部分替换SQL图像数据列

时间:2011-07-09 13:39:41

标签: sql encoding replace hex substring

此问题与我之前发布的another one有关。

总结一下,我需要解决一个古老的遗留应用程序的问题,人们通过以错误的方式重新安装软件来搞乱数据存储。

应用程序通过在SQL DB中保存记录来存储数据。每条记录都包含对磁盘上文件的引用,文件名自动递增。

通过重新安装应用程序,文件名自动增量被重新设置,因此数据库现在拥有多个不相关的记录,这些记录引用相同的文件名,我必须使用文件目录,由于这些相同的文件名,我显然无法合并。这些文件不包含对DB数据的引用,因此剩下的唯一操作过程是在创建的日期过滤DB记录,并尝试将“EXED”重命名为“IXED”或类似的内容。

DB相对简单,一个表包含一个包含“Image”类型数据的列。

该图像数据的示例内容如下:

0x3200001000000000000000200B0000000EFF00000300000031340000000070EC0100002C50000004000000C90000005D010000040000007955B63F4D01000004000000F879883E4F01000004000000BC95563E98010000040000009A99993F4A01000004000000000000004B01000004000000000000009101000004000000000000004E01000004000000721C83425101000004000000D841493F5E01000004000000898828414101000004000000F2D2BD3F4201000004000000FCA9B13F40010000040000007574204244010000040000000000204345010000040000007DD950414601000004000000000000004701000004000000000000009201000004000000000000008701000004000000D2DF13426A0100000400000000005C42740100000400000046B68F40500100000400000018E97A3F7901000004000000FB50CF3C7A01000004000000E645703F99010000040000000000E0404C010000040000008716593F8601000004000000000006439A0100000400000000008040700100000400000063D887449E01000004000000493CBA3E9C0100000400000069699D429B01000004000000DD60CA3F9D0100000400000035DE3C44B4010000040000008B5C744433000000040000003D0ABB4134000000040000000AFF7C44350000000400000093CB39427504000004000 00054A69F41BA010000040000002635C64173040000040000008367C24100000080690100002B5000003101000032000010000000000000002009000000000000000100000000000000F00000000000000080080100000100000010000000540100000100000021F0AA42270000000200000010000000540100000200000021F0AA42280000000300000010000000540100000300000059C9E6432900000004000000100000005401000004000000637888442A00000005000000100000005401000005000000DFEF87442B00000006000000100000005401000006000000000000002C00000007000000100000005401000007000000000000002D00000008000000100000005401000008000000000000002D000000090000001000000054010000090000002F353D442D0000000A00000010000000540100000A00000035DE3C44340000000B00000010000000540100000B0000008B5C7444240000009D50000010000000CDCCCC3E2C513B41F65D5F3F2C51BB419E50000010000000CCBA2C3FE17C8C411553B13F83F32142000000403700000000FE0000090000004558454434386262002D50000008000000447973706E6F65008E5000000E00000056454C442052414D502033363000000000F000000000

数据显然是十六进制,主要编码无意义的垃圾,但也保存了链接到SQL记录的文件系统中物理文件的名称(朝向数据字段的末尾):

??@7???????????EXED48bb?-P??????Dyspnoe??P??????VELD RAMP 360

我对EXED部分感兴趣。

在文件名出现的偏移量和文件名长度可变的情况下没有明确的规律性(所以我事先不知道子字符串的长度)。

我可以使用SQL调用所有记录:

    SELECT COUNT(*) as "Number of EXED Files after critical date"
    FROM [ZAN].[dbo].[zanu]
    WHERE udata is not null 
          and SUBSTRING(udata, 1 , 2147483647) like '%EXED%' 
          and [udatum] > 0 
          and CONVERT(date,[udatum]) > CONVERT(date,'20100629')

我现在要做的是知道如何用其他东西替换这个EXED子字符串(例如IXID)。

我对SQL和谷歌搜索不熟悉到目前为止我的选项信息很少。

我也没有关于生成此数据的原始代码/数据格式/编码/等等的其他信息......

真是一团糟。

欢迎任何帮助!

1 个答案:

答案 0 :(得分:0)

对此的更新:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Threading;

namespace ZANLinq
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                DataContext zanDB = new DataContext(@"Data Source=.\,1433;database=ZAN;Integrated Security=true");


                string strSQL = @"SELECT 
                                    Idnr, 
                                    Udatum, 
                                    Uzeit, 
                                    Unr, 
                                    Uart,
                                    Ubediener, 
                                    Uzugriff, 
                                    Ugr, 
                                    Uflags, 
                                    Usize, 
                                    Udata 
                                 FROM Zanu 
                                 WHERE (Udata IS NOT null and SubString(Udata, 1 , 2147483647) LIKE '%EXED%')
                                 AND (Idnr = '           2')";

                var zanQuery = zanDB.ExecuteQuery<Zanu>(strSQL);

                List<Zanu> list = zanQuery.ToList<Zanu>();

                foreach (Zanu zanTofix in list)
                {
                    string strOriginal = ASCIIEncoding.ASCII.GetString(zanTofix.Udata);
                    string strFixed = strOriginal.Replace("EXED", "IXED");
                    zanTofix.Udata = ASCIIEncoding.ASCII.GetBytes(strFixed);
                }

                zanDB.SubmitChanges();

                //Console.WriteLine(zanResults.Count<Zanu>().ToString());

            }
            catch (SqlException e)
            {
                Console.WriteLine(e.Message);
            }

        }
    }
}

它找到我感兴趣的记录,我可以轻松地操纵数据,但提交不起作用。我很难过,没有例外,没有迹象表明代码是错误的。

有人有想法吗?

<强>更新

我认为上述情况不起作用,因为我的表似乎有一个复合PK(我不能改变这个):

Columns

因为我无法调试这个(没有任何信息,没有例外,只是submitchanges()的静默失败)我决定使用另一种方法并完全放弃Linq2SQL:

try
            {
                SqlConnection thisConnection = new SqlConnection(@"Network Library=DBMSSOCN;Data Source=.\,1433;database=ZAN;Integrated Security=SSPI");

                DataSet zanDataSet = new DataSet();
                SqlDataAdapter zanDa;
                SqlCommandBuilder zanCmdBuilder;

                thisConnection.Open();      

                //Initialize the SqlDataAdapter object by specifying a Select command 
                //that retrieves data from the sample table.
                zanDa = new SqlDataAdapter(@"SELECT 
                                              Idnr, 
                                              Udatum, 
                                              Uzeit, 
                                              Unr, 
                                              Uart,
                                              Ubediener, 
                                              Uzugriff, 
                                              Ugr, 
                                              Uflags, 
                                              Usize, 
                                              Udata 
                                           FROM Zanu 
                                           WHERE (Udata IS NOT null and SubString(Udata, 1 , 2147483647) LIKE '%IXED%')
                                           AND (Idnr = '           2')
                                           AND (Uzeit = '13:21')", thisConnection);

                //Initialize the SqlCommandBuilder object to automatically generate and initialize
                //the UpdateCommand, InsertCommand, and DeleteCommand properties of the SqlDataAdapter.
                zanCmdBuilder = new SqlCommandBuilder(zanDa);

                //Populate the DataSet by running the Fill method of the SqlDataAdapter.
                zanDa.Fill(zanDataSet, "Zanu");

                Console.WriteLine("Records that will be affected: " + zanDataSet.Tables["Zanu"].Rows.Count.ToString());

                foreach (DataRow record in zanDataSet.Tables["Zanu"].Rows)
                {
                    string strOriginal = ASCIIEncoding.ASCII.GetString((byte[])record["Udata"]);
                    string strFixed = strOriginal.Replace("IXED", "EXED");
                    record["Udata"] = ASCIIEncoding.ASCII.GetBytes(strFixed);

                    //string strPostMod = ASCIIEncoding.ASCII.GetString((byte[])record["Udata"]);  
                }

                zanDa.Update(zanDataSet, "Zanu"); 

                thisConnection.Close();

                Console.ReadLine();

            }
            catch (SqlException e)
            {
                Console.WriteLine(e.Message);
            }

这似乎有效,但任何关于为什么Linq不起作用以及我的第二个解决方案是否有效/最佳的输入仍然非常受欢迎。