Прочитайте TXT-файл и преобразуйте его в сценарий SQL - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть текстовый файл:

LoginId; No_Intervenant
EF2KBT0; 1003820030
ENHD0KE; 1003820129
E9PM7EP; 1003820153
EFT10OO; 1003820218

Мне нужно создать другой текстовый файл, содержащий скрипт SQL UPDATE из этой информации, такой как:

UPDATE Contact
Set
Contact.No_Intervenant = '1003820030'
where
ISNULL (Contact.LoginId, '') = 'ER7OZXZ';

Я получил только эторезультат с использованием метода Stringbuilder, но с использованием жесткого кода.Я хотел бы, чтобы заголовок добавлялся автоматически.

public Form1()
{
    InitializeComponent();
}

private static void AddSqlCommand(StringBuilder sql, string[] columns, string[] types, string[] values)
{
    sql.AppendLine("UPDATE Contact");
    sql.AppendLine("SET");
    //skip LoginId columns
    for (int i = 1; i < columns.Length; i++)
    {
        switch (types[i].Trim())
        {
            case "int":                      
                sql.Append($"   Contact.{columns[i].Trim()} = {values[i]}");
                //sql.Append($" Contact.{columns[0].TrimStart() } = {values[i]}");
                break;
            default:
                sql.Append($"   Contact.No_Intervenant = '{values[i]}'");
                break;
        }
        if (columns.Length > 1 && i != columns.Length - 1)
        {
            sql.Append(",");
        }
        sql.AppendLine();
    }
    sql.AppendLine("WHERE");
    sql.AppendLine($"   ISNULL(Contact.LoginId, '') = '{values[0]}';");
    sql.AppendLine();
}

private static StringBuilder GenerateSqlScript(string[] fileContent)
{
    var sqlCommand = new StringBuilder();
    string[] types = fileContent[0].Split(';');
    string[] columns = fileContent[1].Split(';');
    //skip the first line (header)
    for (int i = 2; i < fileContent.Length; i++)
    {
        string[] values = fileContent[i].Split(';');
        if (values.Length >= 1)
        {
            AddSqlCommand(sqlCommand, columns, types, values);
        }
    }
    return sqlCommand;
}

Как я могу автоматически получить и добавить заголовок?Потому что мне, вероятно, придется сделать это для более длинных файлов, с большим количеством столбцов и большим количеством строк обновления для других файлов, и я не хотел бы жестко кодировать все заголовки файлов, как в примере, который я должен сделать далее:

Заголовок:

No_Intervenant; First_Name; Last_Name; Role_SE; EMail; Телефон; Расширение; Statut; Адрес_1; Address_2; ​​Zip; CPF; Inscription_Particulier; DHM_Stat_Part; Date_via_Curl*

Данные:

1003820030; NOEL; SANTOS; Particulier ;;;; Actif; 1528 STREET; VAL-D''OR CA; AAA 5T9; 123456789; Actif ;;2016-07-19 09: 49: 43; 2019-02-08 14: 24: 19;

Ответы [ 4 ]

0 голосов
/ 21 февраля 2019

Просто чтобы опубликовать обновление кода, который я обновил и который на данный момент работает отлично.Спасибо всем за ответы и за помощь.

using System;
using System.IO;
using System.Text;
using System.Windows.Forms;

namespace GenererScriptSQL

{публичный частичный класс Form1: Form {public Form1 () {InitializeComponent ();}

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private static void AddSqlCommand(StringBuilder sql, string[] columns, string[] types, string[] values)
    {
        sql.AppendLine("UPDATE Contact");
        sql.AppendLine("SET");

        //skip LoginId columns
        for (int i = 1; i < columns.Length; i++)
        {
            switch (types[i].Trim())
            {
                case "int":

                    sql.Append($"   Contact.{columns[i].Trim()} = {values[i]}");

                    break;

                default:
                    sql.Append($"   Contact.{columns[i].Trim()} = '{values[i]}'");
                    break;
            }

            if (columns.Length > 1 && i != columns.Length - 1)
            {
                sql.Append(",");
            }

            sql.AppendLine();
        }

        sql.AppendLine();

        sql.AppendLine("WHERE");

        sql.AppendLine();

        sql.AppendLine($"   Contact.{columns[0].Trim()} = '{values[0]}'");

        sql.AppendLine();


    }

    private static StringBuilder GenerateSqlScript(string[] fileContent)
    {
        var sqlCommand = new StringBuilder();
        string[] types = fileContent[0].Split(';');
        string[] columns = fileContent[0].Split(';');

        //skip the first line(header)

        for (int i = 1; i < fileContent.Length; i++)
        {
            string[] values = fileContent[i].Split(';');

            if (values.Length >= 1)
            {
                AddSqlCommand(sqlCommand, columns, types, values);
            }
        }

        return sqlCommand;
    }

    private void buttonCreateSqlFile_Click(object sender, EventArgs e)
    {
        try
        {
            if (IsFileSelected())
            {
                string[] fileContent = File.ReadAllLines(textBoxFile.Text);

                if (fileContent != null)
                {
                    StringBuilder sqlCommand = GenerateSqlScript(fileContent);

                    if (!string.IsNullOrWhiteSpace(sqlCommand.ToString()))
                    {
                        WriteSqlFile(sqlCommand);
                    }
                }


            }
            else
            {
                MessageBox.Show("Sélectionner le fichier de chargement.");
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

    private void buttonSelectFile_Click(object sender, EventArgs e)
    {
        try
        {
            using (var fileBrowser = new OpenFileDialog())
            {
                if (fileBrowser.ShowDialog() == DialogResult.OK)
                {
                    textBoxFile.Text = fileBrowser.FileName;
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

    private bool IsFileSelected()
    {
        return !string.IsNullOrWhiteSpace(textBoxFile.Text) && File.Exists(textBoxFile.Text);
    }

    private void WriteSqlFile(StringBuilder sqlCommand)
    {
        var fileInfo = new FileInfo(textBoxFile.Text);
        string BackupDate = fileInfo.Name + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm") + "_Update" + ".sql";


        string sqlFilePath = Path.Combine(fileInfo.Directory.FullName, BackupDate);

        if (File.Exists(sqlFilePath))
        {
            File.Delete(sqlFilePath);
        }

        File.WriteAllText(sqlFilePath, sqlCommand.ToString());

        MessageBox.Show($@" Le fichier sql a été générée! {sqlFilePath}");
    }
}

}

0 голосов
/ 13 февраля 2019

Я считаю, что в этом случае «MERGE» будет идеальным решением.Это может быть что-то вроде:

-- HEADER --
MERGE [your table] as trg
USING (VALUES

-- DATA FROM THE FILE --
(id, intervenant),
(id, intervenant)

-- FOOTER
) as src(id, intervenant)
ON [your logic from the WHERE statement]
WHEN MATCHED UPDATE SET
trg.[your column] = src.[your column];
0 голосов
/ 13 февраля 2019

Данные из исходного файла могут быть загружены в объект DataTable, из которого затем будут созданы операторы UPDATE.Имена заголовков из файла получены из свойства Columns DataTable, а затем используются для указания столбцов, используемых в скрипте UPDATE.В приведенном ниже примере в сценарий для форматирования добавлены дополнительные строки и разделитель GO.Они не являются необходимыми и могут быть удалены, если вы предпочитаете.

using System.Linq;
using System.Data;
using System.IO;
using System.Text;



     //get source file
    string fullFileName = @"C:\Input Folder\SourceFile.txt";

    DataTable dt = new DataTable();
    StringBuilder sb = new StringBuilder();
    //output .sql script
    string sqlScript = @"C:\Output Folder\UpdateScript.SQL";

   using (StreamReader sr = new StreamReader(fullFileName))
    {
    string firstLine = sr.ReadLine();
    string[] headers = firstLine.Split(';');

    //define columns for data table
    foreach (string h in headers)
    {
        dt.Columns.Add(h);
    }

    int columnCount = dt.Columns.Count;

    string line = sr.ReadLine();

    while (line != null)
    {
    string[] fields = line.Split(';');

    int currentLength = fields.Count();

    if (currentLength < columnCount)
    {
        while (currentLength < columnCount)
        {
            line += sr.ReadLine();
            currentLength = line.Split(';').Count();
        }
        fields = line.Split(';');
    }
    //load data table
    dt.Rows.Add(fields);
    line = sr.ReadLine();
   }

    foreach (DataRow dr in dt.Rows)
       {
        sb.AppendLine("UPDATE Contact SET " + dt.Columns[1] + " = '" + dr[1] + 
      "' WHERE ISNULL(" + dt.Columns[0] + ", '') = '" + dr[0] + "'");

        //extra lines and GO batch separator added between UPDATE statements for formating
        sb.AppendLine(Environment.NewLine);
        sb.AppendLine("GO");
        sb.AppendLine(Environment.NewLine);
       }   
            //output UPDATE commands as .sql script file
            File.WriteAllText(sqlScript, sb.ToString());
      }
0 голосов
/ 13 февраля 2019

Полагаю, вам нужно всего лишь пару простых изменений в вашей интерполяции строк, см. Ниже.Если у вас есть обновление, затрагивающее несколько таблиц, вы должны добавить имя таблицы к столбцу в массиве.

Вот как я тестировал, согласно вашей логике, первая строка файла должна содержать ваши типы данных (пример, который вы разместили не).Так что либо ваша логика неверна, либо выборка данных неверна.Работает с тестовым кодом.

private void button4_Click(object sender, EventArgs e)
        {
            var line = new List<string>();
            line.Add("string;string");
            line.Add("LoginId; No_Intervenant");
            line.Add("EF2KBT0; 1003820030");
            line.Add("ENHD0KE; 1003820129");
            line.Add("E9PM7EP; 1003820153");
            line.Add("EFT10OO; 1003820218");

            var fileContent = line.ToArray();

            var sqlCommand = new StringBuilder();
            string[] types = fileContent[0].Split(';');
            string[] columns = fileContent[1].Split(';');

            //skip the first line (header)
            for (int i = 2; i < fileContent.Length; i++)
            {
                string[] values = fileContent[i].Split(';');

                if (values.Length >= 1)
                {
                    AddSqlCommand(sqlCommand, columns, types, values, "client");
                }
            }

        }

Отредактированная функция:

private static void AddSqlCommand(StringBuilder sql, string[] columns, string[] types, string[] values, string table)
            {
                sql.AppendLine($"UPDATE {table}");
                sql.AppendLine("SET");

                //skip LoginId columns
                for (int i = 1; i < columns.Length; i++)
                {
                    switch (types[i].Trim())
                    {
                        case "int":
                            sql.Append($"   {columns[i].Trim()} = {values[i]}");
                            break;

                        default:
                            sql.Append($"   {columns[i].Trim()} = '{values[i]}'");
                            break;
                    }

                    if (columns.Length > 1 && i != columns.Length - 1)
                    {
                        sql.Append(",");
                    }

                    sql.AppendLine();
                }

                sql.AppendLine("WHERE");
                sql.AppendLine($"   ISNULL({columns[0].Trim()}, '') = '{values[0]}';");
                sql.AppendLine();
            }

        }
...