Avatar billede scorp-d Nybegynder
04. oktober 2011 - 12:07 Der er 5 kommentarer og
1 løsning

Vask data ved backup

Hej,

Hvordan laves der lettest en total backup af en MS Sql database, hvis man samtidig vil have vaskede noget af data'en(sensitiv data).


Fx har jeg en database som indeholder 3 tabeller, hvor jeg gerne vil have slettet alt data fra én af kolonnerne i én af tabellerne.


Om det er vha. Sql, powershell eller C# gør ikke så meget.


På forhånd tak.
Avatar billede arne_v Ekspert
08. oktober 2011 - 22:40 #1
Lav et lille program som kam dumpe en vilkaarlig tabel med en eller flere kolonner udeladt.

Hvis dine data ikke indholder LOB's eller multiline strings saa var det nemmeste nok at lave det MySQL style og genererer INSERT saetninger.

Jeg kan godt lave noget C# kode.
Avatar billede arne_v Ekspert
08. oktober 2011 - 22:41 #2
Men hvad kan du bruge en backup som mangler en kolonne til??
Avatar billede arne_v Ekspert
09. oktober 2011 - 00:42 #3
Noget C# kode som illustrerer:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Text;

namespace E
{
    public class DbDump
    {
        public delegate bool SelectDb(string db);
        public delegate bool SelectTbl(string db, string tbl);
        public delegate bool SelectFld(string db, string tbl,string fld);
        public static void DumpTbl(IDbConnection con, string db, string tbl, StreamWriter sw, SelectFld selfld)
        {
            IDbCommand cmd = con.CreateCommand();
            cmd.CommandText = "USE " + db;
            cmd.ExecuteNonQuery();
            cmd.CommandText = "SELECT * FROM " + tbl;
            List<string> alltbl = new List<string>();
            IDataReader rdr = cmd.ExecuteReader();
            while(rdr.Read())
            {
                string flds = "";
                string vals = "";
                for(int i = 0; i < rdr.FieldCount; i++)
                {
                    if(selfld(db, tbl, rdr.GetName(i)))
                    {
                        if(i > 0)
                        {
                            flds += ",";
                            vals += ",";
                        }
                        flds += rdr.GetName(i);
                        object o = rdr.GetValue(i);
                        if(o is DBNull)
                        {
                            sw.Write("NULL");
                        }
                        else if(o is int
                                || o is long
                                || o is float
                                || o is bool
                                || o is double
                                || o is decimal)
                        {
                            vals += o.ToString();
                        }
                        else if(o is string)
                        {
                            vals += ("'" + o.ToString().Replace("'", "''") + "'");
                        }
                        else
                        {
                            throw new ApplicationException("Unsupported data type");
                        }
                    }
                }
                sw.WriteLine("INSERT INTO {0}({1}) VALUES({2});", tbl, flds, vals);
            }
            rdr.Close();
        }
        public static void DumpDb(IDbConnection con, string db, string catsuf, StreamWriter sw, SelectTbl seltbl, SelectFld selfld)
        {
            sw.WriteLine("USE {0};", db);
            IDbCommand cmd = con.CreateCommand();
            cmd.CommandText = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_" + catsuf + "='" + db + "' AND TABLE_TYPE='BASE TABLE'";
            List<string> alltbl = new List<string>();
            IDataReader rdr = cmd.ExecuteReader();
            while(rdr.Read())
            {
                string tbl = (string)rdr[0];
                if(seltbl(db, tbl))
                {
                    alltbl.Add(tbl);
                }
            }
            rdr.Close();
            foreach(string tbl in alltbl)
            {
                DumpTbl(con, db, tbl, sw, selfld);
            }
        }
        public static void Dump(IDbConnection con, string catsuf, StreamWriter sw, SelectDb seldb, SelectTbl seltbl, SelectFld selfld)
        {
            IDbCommand cmd = con.CreateCommand();
            cmd.CommandText = "SELECT DISTINCT TABLE_" + catsuf + " FROM INFORMATION_SCHEMA.TABLES";
            List<string> alldb = new List<string>();
            IDataReader rdr = cmd.ExecuteReader();
            while(rdr.Read())
            {
                string db = (string)rdr[0];
                if(!db.StartsWith("sys") && !db.Equals("mysql") && seldb(db))
                {
                    alldb.Add(db);
                }
            }
            rdr.Close();
            foreach(string db in alldb)
            {
                DumpDb(con, db, catsuf, sw, seltbl, selfld);
            }
        }
        public static void Dump(string provider, string constr, string catsuf, string fnm, SelectDb seldb, SelectTbl seltbl, SelectFld selfld)
        {
            DbProviderFactory dbf = DbProviderFactories.GetFactory(provider);
            using(IDbConnection con = dbf.CreateConnection())
            {
                con.ConnectionString = constr;
                con.Open();
                using(StreamWriter sw = new StreamWriter(fnm, false, Encoding.UTF8))
                {
                    Dump(con, catsuf, sw, seldb, seltbl, selfld);
                }
            }
        }
        public static void Dump(string provider, string constr, string catsuf, string fnm)
        {
            Dump(provider, constr, catsuf, fnm, (db) => true, (db, tbl) => true, (db, tbl, fld) => true);
        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            DbDump.Dump("System.Data.SqlClient", @"Server=ARNEPC4\SQLEXPRESS;Integrated Security=SSPI;Database=Test", "CATALOG", @"C:\work\ss.txt");
            DbDump.Dump("MySql.Data.MySqlClient", "Data Source=localhost;Database=Test;User Id=root;Password=", "SCHEMA", @"C:\work\ms.txt");
            DbDump.Dump("System.Data.SqlClient", @"Server=ARNEPC4\SQLEXPRESS;Integrated Security=SSPI;Database=Test", "CATALOG", @"C:\work\ss2.txt", (db) => db == "test", (db, tbl) => true, (db, tbl, fld) => fld != "f2");
        }
    }
}
Avatar billede Lars_sm Nybegynder
27. oktober 2011 - 14:12 #4
Hej scorp-d

Du kan ikke gøre det på én gang, hvis jeg forstår din udfordring korrekt.

Hvis det er en kopi af en database, der skal udleveres til en leverandør eller lignende, ville jeg tage en backup af den og restore den under et andet navn - f.eks. med Scrambled til sidst i navnet.

Derefter ville jeg lave et update statement, der forvranskede data i den sensitive kolonne og afvikle det mod databasen der sluttede på Scrambled. Derefter ville jeg tage en backup af Scrambled databasen og udlevere den :)


Mvh Lars Mikkelsen
Avatar billede scorp-d Nybegynder
01. november 2011 - 20:34 #5
#Lars_sm

Ja det var også det jeg var bange for...

Du kan bare lægge et svar.
Avatar billede Lars_sm Nybegynder
01. november 2011 - 20:37 #6
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester