从文本文件动态插入SQLite

时间:2017-10-14 07:39:59

标签: c# sqlite console-application

我试图从文本文件创建动态插入语句,只有SQLite。

到目前为止,我所做的是创建带有必要参数的SQL查询,在运行时添加这些参数,并尝试选择。

但是当我尝试cmd.ExecuteNonQuery();

时,我在try块中遇到错误
  

捕获异常:SQL逻辑错误或缺少数据库   接近" @ 0":语法错误

using System;
using System.Data.SQLite;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Data.SqlClient;

namespace TestApp

    class Program
    {
        static void Main(string[] args)
        {
           //To store the index and column name in the file
           Dictionary<int, string> Columns = new Dictionary<int, string>();
           char[] delimiterChars = { '\t' };
            string createQuery = @" create table if not exists products(id integer not null primary key, name text);
                                insert into products (name) values ('A');
                                insert into products (name) values ('B');
                                insert into products (name) values ('C');
                                insert into products (name) values ('D');
                                insert into products (name) values ('E');
                                insert into products (name) values ('F');
                                insert into products (name) values ('G');
                                create table if not exists orders(id integer, dt datetime, product_id integer, amount real);"; 
        System.Data.SQLite.SQLiteConnection.CreateFile("myDB.db3");
        using (System.Data.SQLite.SQLiteConnection conn = new System.Data.SQLite.SQLiteConnection("data source=myDB.db3")){
            using (System.Data.SQLite.SQLiteCommand cmd = new System.Data.SQLite.SQLiteCommand(conn)){
                conn.Open();
                cmd.CommandText = createQuery;
                cmd.ExecuteNonQuery();
                string[] lines = System.IO.File.ReadAllLines(Directory.GetCurrentDirectory() + @"../../../App_Data/import.txt");
                cmd.CommandText = "INSERT INTO orders (";
                // Identify the column order from first row of the import file
                string[] elements = lines[0].Split(delimiterChars);
                for (int i = 0; i < elements.Length; i++)
                {
                    Columns[i] = elements[i];
                    cmd.CommandText = cmd.CommandText + "@COLUMN" + i + ", ";
                    cmd.Parameters.AddWithValue("@COLUMN" + i, Columns[i]);
                    System.Console.WriteLine(i + " : " + Columns[i]);

                }
                cmd.CommandText = cmd.CommandText.Remove(cmd.CommandText.Length - 2);
                cmd.CommandText = cmd.CommandText + ") VALUES (";
                string temp = cmd.CommandText;
                System.Console.WriteLine(cmd.CommandText);
                System.Console.WriteLine("Contents of Import File.txt = ");
                for (int i = 1; i < lines.Length; i++)
                {
                    cmd.CommandText = temp;
                    elements = lines[i].Split(delimiterChars);
                    for (int j = 0; j < elements.Length; j++)
                    {
                        cmd.CommandText = cmd.CommandText + "@VALUE" + j + ", ";
                        cmd.Parameters.AddWithValue("@VALUE" + j, elements[j]);
                    }
                    cmd.CommandText = cmd.CommandText.Remove(cmd.CommandText.Length - 2);
                    cmd.CommandText = cmd.CommandText + ")";
                    try
                    {
                        cmd.ExecuteNonQuery();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Caught exception: " + ex.Message);
                    }

                    Console.WriteLine(cmd.CommandText);
                    Console.WriteLine(lines[i]);
                }

                cmd.CommandText = "Select * from orders";
                cmd.ExecuteNonQuery();
                using (System.Data.SQLite.SQLiteDataReader reader = cmd.ExecuteReader()){
                    while (reader.Read())
                    {
                        Console.WriteLine(reader["ID"] + " | " + reader["dt"] + " | " + reader["product_id"] + " | " + reader["amount"]);
                    }
                    conn.Close();
                }
            }
        }
        Console.WriteLine("Press any key to exit.");
        Console.ReadLine();
    }
}
}

我不确定我做错了什么?

import.txt文件由

组成
id  dt  amount  product_id
1   2017-02-01T10:01:12 343.33  1
2   2017-02-01T10:02:12 12  2
3   2017-03-01T10:03:12 344.3   1
4   2017-04-01T10:04:12 12  3
5   2017-05-01T10:05:12 66.5    1
6   2017-06-01T10:06:12 4   

所有项目除以TAB

1 个答案:

答案 0 :(得分:3)

列名称循环没用,因为您已经知道第一行执行的CREATE TABLE ORDERS命令中的列名。
顺便说一句,您不能使用参数来表示列的名称 在我所知的任何类型的数据库系统中都不允许这样做。

您可以安全地删除它,但请注意您已错误地声明了列顺序。在CREATE TABLE中你有

create table if not exists orders(
id integer, dt datetime, product_id integer, amount real

在文件中 product_id 是最后一列。所以你需要调整你的CREATE TABLE到你的文件

create table if not exists orders(
id integer, dt datetime, amount real, product_id integer;

接下来你的插入循环代码可以用这种方式重写(在解释时忽略可变数量的参数)

string baseQuery = "INSERT INTO orders (id, dt, amount, product_id ) VALUES(";
string[] lines = System.IO.File.ReadAllLines(@"e:\temp\orders.txt");

// Skip the first line
for (int i = 1; i < lines.Length; i++)
{
    string[] elements = lines[i].Split(delimiterChars);

    // Keep the parameter names in a list to get an easy way to 
    // concatenate them all together at the end of the loop
    List<string> text = new List<string>();
    for (int j = 0; j < elements.Length; j++)
    {
        text.Add("@VALUE" + j);
        cmd.Parameters.AddWithValue("@VALUE" + j, elements[j]);
    }
    // Create the command text in a single shot
    cmd.CommandText = baseQuery + string.Join(",", text) + ")";
    try
    {
        cmd.ExecuteNonQuery();
    }
    catch (Exception ex)
    {
        Console.WriteLine("Caught exception: " + ex.Message);
    }
}

考虑将您的数据库代码包含在这样的事务中,如下面由Alexander Petrov发布的链接所示

using (System.Data.SQLite.SQLiteConnection conn = new System.Data.SQLite.SQLiteConnection("data source=myDB.db3"))
using (System.Data.SQLite.SQLiteCommand cmd = new System.Data.SQLite.SQLiteCommand(conn))
{
     conn.Open();
     using(SQLiteTransaction tr = conn.BeginTransaction())
     {
         cmd.Transaction = tr;
         .....
         for(....)
         {
             .....
         }
         tr.Commit();
     }
}