Backend - C# 操作PostgreSQL DB

news2024/9/28 15:33:41

目录

一、安装 Npgsql 插件

(一)作用

(二)操作

(三)注意

二、操作类

(一)操作类

1.NpgsqlConnection类

(1)作用

(2)引入

(3)数据库路由

(4)连接数据库

2.NpgsqlCommand类

(1)作用

(2)应用

(3)方法

       ① ExecuteNonQuery()  不返回任何结果。

        ② ExecuteScalar()  返回一个值。可搭配ExecuteScalar().ToString();输出值。

        ③ ExecuteReader()  返回一个IDataReader。

3.NpgsqlDataReader类

(1)作用

(2)应用

4.DataSet类

(1)作用

(2)应用

5.DataAdapter类:数据适配命令

(1)结合DataSet类,将数据可存储在DataSet对象中

(2)DataAdapter属性

(3)DataAdapter方法

(4)应用

(二)using

三、连接数据库

1. 简单写法

2. 灵活写法

四、操作数据库

(一)创建&删除表

(二)插入

 1. 单笔插入

(1)使用NpgsqlCommand

(2)使用BeginBinaryImport

① 定义时

② 调用时

 2. 批量插入

(三)查询

(四)更新

 1. 批量更新

五、写法

(一)字符串中的双引号

        1. 用@符号+“”两个双引号

        2. 用 \" 转义

六、问题

 1. 问题:于 Npgsql.NpgsqlException 擲回例外狀況: 'mscorlib.dll'

 2. 问题:42601: INSERT has more target columns than expressions 和 42601: syntax error at or near "[" 这两个问题

 3. 问题:Binary importer closed in the middle of a row, cancelling import.

 4. 问题:22P03: incorrect binary data format

 5. 问题:Binary importer closed in the middle of a row, cancelling import.

 6. 问题:error: Write for column 17 resolves to a different PostgreSQL type: OID 1114 than the first row resolved to (OID 0). Please make sure to use clr types that resolve to the same PostgreSQL type across rows. Alternatively pass the same NpgsqlDbType or DataTypeName to ensure the PostgreSQL type ends up to be identical.

 7. 问题:The binary import operation was started with 23 column(s), but 24 value(s) were provided.

 8. 问题: 22021: invalid byte sequence for encoding "UTF8": 0x00

 9. 问题:Writing values of 'System.DateTimeOffset' is not supported for parameters having NpgsqlDbType 'Timestamp'.

 10. 问题:Cannot write DateTimeOffset with Offset=08:00:00 to PostgreSQL type 'timestamp with time zone', only offset 0 (UTC) is supported.

 11. 问题:error: Cannot write DateTime with Kind=Unspecified to PostgreSQL type 'timestamp with time zone', only UTC is supported. Note that it's not possible to mix DateTimes with different Kinds in an array, range, or multirange.


注意,这篇文章主要都是针对npgsql ,而不是sql。

一、安装 Npgsql 插件

(一)作用

        Npgsql是用C#语言编写的,符合ADO.NET规范的,操作PostgreSQL数据库的驱动插件。

(二)操作

        点击工具栏的“工具” > NuGet套件管理员 > 套件管理器主控台。

        打开控制台后,输入安装命令:

Install-Package Npgsql

        安装成功后会提示:

(三)注意

        不同解决方案在使用Npgsql,都需要各自安装一次。

        查看或勾选安装:点击工具栏的“工具” > NuGet套件管理员 > 管理方案的NuGet套件(程式若启动了,先终止运行) > 搜寻插件名 > 查看某项目是否安装。

二、操作类

(一)操作类

        核心有:NpgsqlConnection、NpgsqlCommand、NpgsqlDataReader、DataSet和DataAdapter、NpgsqlDataProvider。

1.NpgsqlConnection类

(1)作用

        创建数据库的连接。

(2)引入
using Npgsql;
(3)数据库路由
string DbUrl = "Host=127.0.0.1;Port=5432;Database=TestPro;Username=postgres;Password=root;";
(4)连接数据库
NpgsqlConnection DbConn = new NpgsqlConnection(DbUrl);
DbConn.Open();
DbConn.Close();

2.NpgsqlCommand类

(1)作用

        执行SQL命令

(2)应用
// 第1种
using var cmd1 = new NpgsqlCommand();
cmd1.Connection = DbConn;
cmd1.CommandText = sqlstr;
cmd1.ExecuteNonQuery();

// 第2种
NpgsqlCommand cmd2 = new NpgsqlCommand(sqlstr, DbConn);
cmd2.ExecuteNonQuery();
(3)方法
       ① ExecuteNonQuery()  不返回任何结果。

        举例:

cmd.CommandText = "DROP TABLE IF EXISTS book"; // 如果book表存在,则删掉
cmd.ExecuteNonQuery();

cmd.CommandText = @"CREATE TABLE book(id SERIAL PRIMARY KEY,
    bookname VARCHAR(255), bookprice INT)";
cmd.ExecuteNonQuery();

cmd.CommandText = "INSERT INTO cars(name, price) VALUES('Volkswagen',21600)";
cmd.ExecuteNonQuery();
        ② ExecuteScalar()  返回一个值。可搭配ExecuteScalar().ToString();输出值。
        ③ ExecuteReader()  返回一个IDataReader。

3.NpgsqlDataReader类

(1)作用

        读取数据。

(2)应用
NpgsqlConnection sourceConn = new NpgsqlConnection(sourceUrl);
NpgsqlCommand s_cmd = new NpgsqlCommand("select * from public.\"myApp_book\" limit 100", sourceConn);
NpgsqlDataReader reader = s_cmd.ExecuteReader();
while (reader.Read()) // 循环
 {
     Console.WriteLine($"first value:{reader.GetValue(0)}, second value: {reader.GetValue(1)}"); //使用下标取值
 }

4.DataSet类

(1)作用

        离线处理大量数据,得到数据集

(2)应用

        搭配DataAdapter类

5.DataAdapter类:数据适配命令

(1)结合DataSet类,将数据可存储在DataSet对象中
(2)DataAdapter属性

        SelectCommand:选取数据源中的记录;

        InsertCommand:向数据源中新插入一条记录;

        UpdateCommand:更新数据源中的数据;

        DeleteCommand:删除数据源中的记录。

(3)DataAdapter方法

        Fill:从数据源增加或刷新行,并将这些行放到DataSet表中。

        Updata:将DataSet表的更改传送到相应的数据源中。

(4)应用
var npgsqlDataAdapter = new NpgsqlDataAdapter();
npgsqlDataAdapter.SelectCommand = new NpgsqlCommand("select * from public.\"myApp_book\" limit 100", sourceConn);
var dataSet = new DataSet();
npgsqlDataAdapter.Fill(dataSet);//将数据填充到dataSet
dataSet.Tables[0]; //获取dataSet的table数据

(二)using

        using语句在变量超出范围时,释放数据库连接资源。

        举例:

using var con = new NpgsqlConnection(targetUrl);
using var cmd = new NpgsqlCommand(sql, con);

三、连接数据库

举例:

1. 简单写法

using Npgsql;
using System;

class TestConnDB
{
    static void Main(string[] args)
    {
        string DbUrl = "Host=127.0.0.1;Port=5432;Database=TestPro;Username=postgres;Password=admin;";
        NpgsqlConnection DbConn = new NpgsqlConnection(DbUrl);
        try
        {
            DbConn.Open();
            Console.WriteLine("connect success!");
            Console.ReadKey();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.ReadKey();
        }
        DbConn.Close();
    }
}

2. 灵活写法

using CommSettingSpace;
using Npgsql;
using System;
using System.Collections.Generic;

namespace DBSpace
{
    //---------设置DB详情
    class CommSetting
    {
        //-------------------------设置Source DB信息
        public static Dictionary<string, string> SourceDbInfo = new Dictionary<string, string>
        { // 用static,则使用该方法时,不用实例化所属类
            { "Host", "127.0.0.1" },
            { "Port", "5432" },
            { "Database", "bookDb" },
            { "Username", "admin" },
            { "Password", "123" }
        };

        //-------------------------设置Target DB信息
        public static Dictionary<string, string> TargetDbInfo = new Dictionary<string, string>
        {
            { "Host", "127.0.0.1" },
            { "Port", "5432" },
            { "Database", "copyBookDb" },
            { "Username", "postgres" },
            { "Password", "456" }
        };
    }

    // ---------设置DB连接
    class SetDBConn
    {
        public string PgUrl(Dictionary<string, string> Db)
        {
            return $"Host={Db["Host"]};Port={Db["Port"]};Database={Db["Database"]};Username={Db["Username"]};Password={Db["Password"]};";
        }
    }

    // ---------执行项目
    class Test
    {
        //main方法(测试连接不同数据库)
        static void Main(string[] args)
        {
            try
            {
                //连接第1个数据库(比如在拷贝数据时,这是来源数据库)
                SetDBConn sourceDB = new SetDBConn();
                string sourceUrl = sourceDB.PgUrl(CommSetting.SourceDbInfo);
                NpgsqlConnection sourceConn = new NpgsqlConnection(sourceUrl);

                //连接第2个数据库(这是目标数据库)
                SetDBConn targetDB = new SetDBConn();
                string targetUrl = targetDB.PgUrl(CommSetting.TargetDbInfo);
                NpgsqlConnection targetConn = new NpgsqlConnection(targetUrl);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"error: {ex.Message}");
                Console.ReadKey();
            }
        }
    }
}

四、操作数据库

(一)创建&删除表

using Npgsql;
using Npgsql.Internal;
using NpgsqlTypes;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text.Json.Serialization;

namespace DBConnSpace
{
    // ---------设置DB连接
    class SetDBConn
    {
        public string PgUrl(string db_host, string db_port, string db_dbname, string db_user, string db_pwd)
        {
            return $"Host={db_host};Port={db_port};Database={db_dbname};Username={db_user};Password={db_pwd};";
        }
    }
    class Test
    {
        //main方法
        static void Main(string[] args)
        { 
            //-------------------------设置Pg DB信息
            SetDBConn sourceDB = new SetDBConn();
            string sourceUrl = sourceDB.PgUrl("127.0.0.1", "5432", "TestPro1219DB", "postgres", "root");
            NpgsqlConnection sourceConn = new NpgsqlConnection(sourceUrl);

            SetDBConn targetDB = new SetDBConn();
            string targetUrl = targetDB.PgUrl("127.0.0.1", "5432", "TestPro1219DB", "postgres", "root");
            NpgsqlConnection targetConn = new NpgsqlConnection(targetUrl);
            try
            {
                //-------------------------打开数据库
                sourceConn.Open();
                targetConn.Open();
                Console.WriteLine("connect success!");
                //-------------------------创建数据库表
                NpgsqlCommand cmd2 = new NpgsqlCommand(@"CREATE TABLE book(id SERIAL PRIMARY KEY, bookname VARCHAR(255), bookprice INT)", targetConn);
	    -------------------------删除已存在的数据库表
	    //NpgsqlCommand cmd2 = new NpgsqlCommand(@"DROP TABLE IF EXISTS book", targetConn);
                cmd2.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadKey();
            }
            sourceConn.Close();
            targetConn.Close();
        }
    }
}

(二)插入

 1. 单笔插入

(1)使用NpgsqlCommand
using Npgsql;
using Npgsql.Internal;
using NpgsqlTypes;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text.Json.Serialization;

namespace DBConnSpace
{
    // ---------设置DB连接
    class SetDBConn
    {
        public string PgUrl(string db_host, string db_port, string db_dbname, string db_user, string db_pwd)
        {
            return $"Host={db_host};Port={db_port};Database={db_dbname};Username={db_user};Password={db_pwd};";
        }
    }
    class Test
    {
        static void Main(string[] args)
        {
            //-------------------------设置Pg DB信息
            SetDBConn sourceDB = new SetDBConn();
            string sourceUrl = sourceDB.PgUrl("127.0.0.1", "5432", "TestPro1219DB", "postgres", "root");
            NpgsqlConnection SourceConn = new NpgsqlConnection(sourceUrl);

            SetDBConn targetDB = new SetDBConn();
            string targetUrl = targetDB.PgUrl("127.0.0.1", "5432", "TestPro1219DB", "postgres", "root");
            NpgsqlConnection targetConn = new NpgsqlConnection(targetUrl);

            try
            {
                //-------------------------打开数据库
                SourceConn.Open();
                targetConn.Open();
                Console.WriteLine("connect success!");
                //-------------------------插入Target DB(单笔)
                NpgsqlCommand t_cmd = new NpgsqlCommand("insert into \"myApp_book\" " +
                    "(card, name, author, btype, price, num) values " +
                    "(@card, @name, @author, @btype, @price, @num)", targetConn);
                t_cmd.Parameters.AddWithValue("@card", "T1F001");
                t_cmd.Parameters.AddWithValue("@name", "T数据结构");
                t_cmd.Parameters.AddWithValue("@author", "萝卜吖");
                t_cmd.Parameters.AddWithValue("@btype", "T教育");
                t_cmd.Parameters.AddWithValue("@price", 101);
                t_cmd.Parameters.AddWithValue("@num", 12);
                object res = t_cmd.ExecuteNonQuery();
                Console.WriteLine(res); // 返回插入笔数


                Console.WriteLine("select success!");
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadKey();
            }
            SourceConn.Close();
            targetConn.Close();
        }
    }
}
(2)使用BeginBinaryImport
① 定义时
public void SoloInsertDbData(List<Dictionary<string, object>> datalist, NpgsqlConnection conn, string copysql)

{

    using (var writer = conn.BeginBinaryImport(copysql))

    {

        writer.StartRow();

        foreach (var item in datalist)

        {

            NpgsqlDbType keyType = (NpgsqlDbType)Convert.ChangeType(item["key"], typeof(NpgsqlDbType));

            writer.Write(item["val"], keyType);

        }

        writer.Complete(); // 直接操作数据库

    }

    Console.WriteLine("one insert success!");

}
② 调用时
string targetUrl = "Host=127.0.0.1;Port=5432;Database=TestPro;Username=postgres;Password=root;"
NpgsqlConnection targetConn = new NpgsqlConnection(targetUrl);
targetConn.Open();
var hisdata = new List<Dictionary<string, object>> //列表包字典
{
    new Dictionary<string, object> { { "key", NpgsqlDbType.TimestampTz }, { "val", DateTime.UtcNow } },
    new Dictionary<string, object> { { "key", NpgsqlDbType.Varchar }, { "val", "failure_analysis" } },
    new Dictionary<string, object> { { "key", NpgsqlDbType.Varchar }, { "val", tbtime } },
    new Dictionary<string, object> { { "key", NpgsqlDbType.Varchar }, { "val", nowtime } },
};
var addhissql =@"copy ""rep_updhist""(lastupdate, tablename, starttimekey, endtimekey) FROM STDIN BINARY";
tl.SoloInsertDbData(hisdata, targetConn, addhissql);

 2. 批量插入

using Npgsql;
using Npgsql.Internal;
using NpgsqlTypes;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text.Json.Serialization;

namespace DBConnSpace
{
    // ---------设置DB连接
    class SetDBConn
    {
        public string PgUrl(string db_host, string db_port, string db_dbname, string db_user, string db_pwd)
        {
            return $"Host={db_host};Port={db_port};Database={db_dbname};Username={db_user};Password={db_pwd};";
        }
    }
    class Test
    {
        static void Main(string[] args)
        {
            //-------------------------设置Pg DB信息
            SetDBConn sourceDB = new SetDBConn();
            string sourceUrl = sourceDB.PgUrl("127.0.0.1", "5432", "TestPro1219DB", "postgres", "root");
            NpgsqlConnection SourceConn = new NpgsqlConnection(sourceUrl);

            SetDBConn targetDB = new SetDBConn();
            string targetUrl = targetDB.PgUrl("127.0.0.1", "5432", "TestPro1219DB", "postgres", "root");
            NpgsqlConnection targetConn = new NpgsqlConnection(targetUrl);

            try
            {
                //-------------------------打开数据库
                SourceConn.Open();
                targetConn.Open();
                Console.WriteLine("connect success!");

                //-------------------------获取Source DB
                //使用DataAdapter查询(会自动断开链接,把数据存在内存里)
                var npgsqlDataAdapter = new NpgsqlDataAdapter();
                npgsqlDataAdapter.SelectCommand = new NpgsqlCommand("select * from public.\"myApp_book\" limit 100", SourceConn);
                //将数据填充到dataTable
                var dataTable = new DataTable();
                npgsqlDataAdapter.Fill(dataTable);

                //-------------------------插入Target DB(批量)
                //第1种:插入写死的测试数据,即直接插入的完整sql
                NpgsqlCommand t_cmd1 = new NpgsqlCommand("insert into \"myApp_book\" " +
                    "(card, name, author, btype, price, num) values " +
                    "('T1F001', 'T数据结构', '萝卜吖', 'T教育', 101, 22), " +
                    "('T1F002', 'T操作系统', '玉米吖', 'T教育', 102, 33)", targetConn);
                object res1 = t_cmd1.ExecuteNonQuery();
                Console.WriteLine(res1); // 返回插入笔数

                //第2种:将SourceDB的数据重新整理,拼接字串
                var sqlstr = "insert into \"myApp_book\" " + "(card, name, author, btype, price, num) values ";
                foreach (DataRow record in dataTable.Rows)
                {
                    sqlstr = sqlstr + "('" + record["card"] + "','" + record["name"] +
                        "','" + record["author"] + "','" + record["btype"] +
                        "'," + record["price"] + "," + record["num"] + "),";
                }
                sqlstr = sqlstr.Substring(0, sqlstr.Length - 1); // 移除字符串的最后一个字符
                NpgsqlCommand t_cmd2 = new NpgsqlCommand(sqlstr, targetConn);
                object res2 = t_cmd2.ExecuteNonQuery();
                Console.WriteLine(res2); // 返回插入笔数

                //第3种:将SourceDB的数据重新整理,使用BeginBinaryImport和copy
	    // 使用注意事项:确保每列各自存取的所有数据类型都一致。
                var writer = targetConn.BeginBinaryImport("copy \"myApp_book\"(card, name, author, btype, price, num) FROM STDIN BINARY");
                foreach (DataRow record in dataTable.Rows)
                {
                    writer.StartRow();
                    writer.Write(record["card"]); // 只是整理数据,不会直接操作数据库
                    writer.Write(record["name"]);
                    writer.Write(record["author"]);
                    writer.Write(record["btype"]);
                    writer.Write(record["price"]);
                    writer.Write(record["num"]);

		//writer.StartRow();
		//foreach (DataColumn col in dbdata.Columns) // 每个单元格
		//{
		//    writer.Write(record[col]); // 只是整理数据,不会直接操作数据库
		//}

                }
                writer.Complete(); // 直接操作数据库

	     Console.WriteLine($"bulk insert success, count( {dbdata.Rows.Count} )"); // 操作笔数
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadKey();
            }
            SourceConn.Close();
            targetConn.Close();
        }
    }
}

(三)查询

using Npgsql;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace DBConnSpace
{
    // ---------设置DB连接
    class SetDBConn
    {
        public string PgUrl(string db_host, string db_port, string db_dbname, string db_user, string db_pwd)
        {
            return $"Host={db_host};Port={db_port};Database={db_dbname};Username={db_user};Password={db_pwd};";
        }
    }
    class Test
    {
        static void Main(string[] args)
        {
            //-------------------------设置Pg DB信息
            SetDBConn sourceDB = new SetDBConn();
            string sourceUrl = sourceDB.PgUrl("127.0.0.1", "5432", "TestPro1219DB", "postgres", "root");
            NpgsqlConnection SourceConn = new NpgsqlConnection(sourceUrl);

            SetDBConn targetDB = new SetDBConn();
            string targetUrl = targetDB.PgUrl("127.0.0.1", "5432", "TestPro1219DB", "postgres", "root");
            NpgsqlConnection targetConn = new NpgsqlConnection(targetUrl);

            try
            {
                //-------------------------打开数据库
                SourceConn.Open();
                targetConn.Open();
                Console.WriteLine("connect success!");

                //-------------------------获取Source DB
                //(1)使用DataAdapter查询(会自动断开链接,把数据存在内存里)
                var npgsqlDataAdapter = new NpgsqlDataAdapter();
                npgsqlDataAdapter.SelectCommand = new NpgsqlCommand("select * from public.\"myApp_book\" limit 100", SourceConn);

                //1.1 使用DataTable
                var dataTable = new DataTable();
                npgsqlDataAdapter.Fill(dataTable);//将数据填充到dataTable
	   // 1.1.1 获取很多列的数据
                foreach (DataRow dataTableRow in dataTable.Rows)
                {
                    Console.WriteLine($"first value:{dataTableRow["bid"]}, second value: {dataTableRow["card"]}");
                }
	   // 1.1.2 获取某列的所有数据
		//将$ "
		// 注意,其中 npgsqlDataAdapter.SelectCommand的查询语句如下
		// npgsqlDataAdapter.SelectCommand = new NpgsqlCommand("select array_agg(distinct bookname) bookname from \"book\", SourceConn);
		if (dt.Rows.Count > 0)
		{
		    var bknames = (object[])dt.Rows[0]["bookname"]; // 获取聚合后的数组
		    foreach (var bk in bknames)
		    {
		        Console.WriteLine(bk); // 打印每个书名
		    }
		}


                //1.2 使用DataSet
                Console.WriteLine();
                var dataSet = new DataSet();
                npgsqlDataAdapter.Fill(dataSet);//将数据填充到dataSet
                var dataTable2 = new DataTable();
                dataTable2 = dataSet.Tables[0]; //将dataSet的table数据填充到dataTable
                foreach (DataRow dataTableRow in dataTable2.Rows)
                {
                    Console.WriteLine($"first value:{dataTableRow["bid"]}, second value: {dataTableRow["card"]}");
                }

                //foreach (DataRow row in dataTable.Rows) // 每行
                //{
                //    foreach (DataColumn col in dataTable.Columns) // 每个单元格
                //    {
                //        Console.Write(row[col] + "\t");
                //    }
                //    Console.WriteLine();
                //}

                //(2)使用DataReader查询
                Console.WriteLine();
                NpgsqlCommand s_cmd = new NpgsqlCommand("select * from public.\"myApp_book\" limit 100", SourceConn);
                NpgsqlDataReader reader = s_cmd.ExecuteReader();
                if (reader.Read()) // 是否有数据
                {
                    //使用下标取字段名
                    Console.WriteLine($"BookID: {reader.GetName(0).ToString()}, BookName: {reader.GetName(1).ToString()}");
                }
                while (reader.Read()) // 循环
                {
                    //使用下标取值
                    Console.WriteLine($"first value:{reader.GetValue(0)}, second value: {reader.GetValue(1)}");
                    //使用字段取值
                    Console.WriteLine($"first value:{reader["bid"].ToString()}, second value:{reader["card"].ToString()}");
                }
                
                Console.WriteLine("select success!");
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadKey();
            }
            SourceConn.Close();
            targetConn.Close();
        }
    }
}

(四)更新

 1. 批量更新

using DBConnSpace;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace TestCls
{
    class Program
    {
        static void Main()
        {
            //-------------------------设置Pg DB信息
            string sourceUrl = "Host=127.0.0.1;Port=5432;Database=TestPro1219DB;Username=postgres;Password=root";
            var sourceConn = new NpgsqlConnection(sourceUrl);
            string targetUrl = "Host=127.0.0.1;Port=5432;Database=TestPro1219DB;Username=postgres;Password=root";
            var targetConn = new NpgsqlConnection(targetUrl);
            sourceConn.Open();
            targetConn.Open();
            try
            {
                //-------------------------使用sqlBuilder拼接SQL语句
                StringBuilder sqlBuilder = new StringBuilder();
                StringBuilder sqlBuilder2 = new StringBuilder();
                StringBuilder sqlBuilder3 = new StringBuilder();
                sqlBuilder.AppendLine("UPDATE \"myApp_book\" SET price = CASE bid ");
                sqlBuilder2.AppendLine(" END, name = CASE bid ");
                sqlBuilder3.AppendLine(" WHERE bid IN ( ");

                // 定义一个字典,包含了需要更新的bid和对应的新价格和新名称
                //var update_data = new Dictionary<int, object[]>
                //{
                //    { 1, new object[] { 132, "数据库原理2" } }, // 更新bid为1的书籍价格为132,名称为“数据库原理2”
                //    { 2, new object[] { 134, "数据结构2" } }  // 更新bid为2的书籍价格为134,名称为“数据结构2”
                //};
                //foreach (var upd in update_data)
                //{
                //    sqlBuilder.AppendFormat(" WHEN {0} THEN {1} ", upd.Key, upd.Value[0]);
                //    sqlBuilder2.AppendFormat(" WHEN {0} THEN '{1}' ", upd.Key, upd.Value[1]);
                //    sqlBuilder3.AppendFormat(" {0}, ", upd.Key);
                //}
                //sqlBuilder.AppendLine($"{sqlBuilder2.ToString()} END {sqlBuilder3.ToString()} 0 ); ");
                var npgsqlDataAdapter = new NpgsqlDataAdapter();
                npgsqlDataAdapter.SelectCommand = new NpgsqlCommand("select * from \"myApp_book\" where bid in (1,2,3)", sourceConn);
                var dataTable = new DataTable();
                npgsqlDataAdapter.Fill(dataTable);//将数据填充到dataTable
                foreach (DataRow dataTableRow in dataTable.Rows)
                {
                    sqlBuilder.AppendFormat(" WHEN {0} THEN {1} ", dataTableRow["bid"], dataTableRow["price"]); // 条件是bid,值是price
                    sqlBuilder2.AppendFormat(" WHEN {0} THEN \'{1}\' ", dataTableRow["bid"], dataTableRow["name"]); // 条件是bid,值是name
                    sqlBuilder3.AppendFormat(" {0}, ", dataTableRow["bid"]); // where 所有条件
                }
                sqlBuilder.AppendLine($"{sqlBuilder2.ToString()} END {sqlBuilder3.ToString()} 0 ); ");

                var command = new NpgsqlCommand(sqlBuilder.ToString(), targetConn);
                command.ExecuteNonQuery();
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            sourceConn.Close();
            targetConn.Close();
        }
    }
}

五、写法

(一)字符串中的双引号

        1. 用@符号+“”两个双引号

        其中,@符号包裹的内容里,两个双引号表示一个双引号。

@"select * from public.""myApp_book"" limit 100"

        2. 用 \" 转义

"select * from public.\"myApp_book\" limit 100"

六、问题

 1. 问题:于 Npgsql.NpgsqlException 擲回例外狀況: 'mscorlib.dll'

        解决:这个问题表达不明确,则自己写trycatch捕捉异常,并使用Console.ReadKey()让异常保留在exe控制台上查看。

 2. 问题:42601: INSERT has more target columns than expressions 和 42601: syntax error at or near "[" 这两个问题

        原因:批量添加时,不能使用[ ]或( )括号等来包裹批量记录,直接用逗号隔开每笔记录就好。

        解决:取消外括号 ( )或[ ]

 3. 问题:Binary importer closed in the middle of a row, cancelling import.

        原因:要插入的列数和表格的列数不一致。

        解决:列数和列值类型一定要对应。

 4. 问题:22P03: incorrect binary data format

        原因:在使用BeginBinaryImport()的writer.Write()时,插入值的列类型存在不同。

        解决:writer.Write()中定义列类型。

        举例:

copysql = @"copy ""book""(publishdate, author, price, num) FROM STDIN BINARY";
datalist = new List<object> { DateTime.UtcNow, "数据结构", 12.3, 100};
using (var writer = conn.BeginBinaryImport(copysql))
{
	writer.StartRow();
	writer.Write(datalist[0], NpgsqlDbType.TimestampTz); // 时间戳
	writer.Write(datalist[1], NpgsqlDbType.Varchar); // varchar类型
	writer.Write(datalist[2], NpgsqlDbType.Float);  // 浮点数
	writer.Write(datalist[3], NpgsqlDbType.Integer);  // 整数
	writer.Complete(); // 直接操作数据库
}

 5. 问题:Binary importer closed in the middle of a row, cancelling import.

        原因:在使用BeginBinaryImport()的writer.Write()之前,没有写writer.StartRow();。

        解决:在使用BeginBinaryImport()之后,writer.Write()之前,补充writer.StartRow();。

 6. 问题:error: Write for column 17 resolves to a different PostgreSQL type: OID 1114 than the first row resolved to (OID 0). Please make sure to use clr types that resolve to the same PostgreSQL type across rows. Alternatively pass the same NpgsqlDbType or DataTypeName to ensure the PostgreSQL type ends up to be identical.

        原因:使用 BeginBinaryImport 的 Write<T>(T, NpgsqlDbType) 时,循环每笔数据的NpgsqlDbType类型不匹配。

        比如,针对某表,需要存入20笔记录,在write时会根据第一笔记录产生的NpgsqlDbType来定义每列类型。当前16笔的时间列值都是null,第17笔的时间列值突然不为空了,变成“2024-03-19 10:05:44.561 +0800”有值了,则write时的类型就会不匹配,然后报错。

        解决:确保每列各自存放的数据类型都一致。

 7. 问题:The binary import operation was started with 23 column(s), but 24 value(s) were provided.

        原因:使用 BeginBinaryImport 的 Write<T>(T, NpgsqlDbType) 时,write有多写。

        解决:检查write所在的代码

 8. 问题: 22021: invalid byte sequence for encoding "UTF8": 0x00

        原因:

        (1)使用 BeginBinaryImport 的 Write<T>(T, NpgsqlDbType) 时,没有定义write类型。然后循环时某列每笔的数据类型不一致。

        (2)表示数据库中可能插入了 NULL 值,需要转换格式为DBNull.Value。如: if (DBNull.Value.Equals(record[col])) { colval = DBNull.Value; } 。

        (3)定义的NpgsqlDbType不准确。

        (4)插入的数据,在Write时,自动转变为适应的数据格式,与数据库想要的格式不符合。

        解决:

using (var writer = conn.BeginBinaryImport(copysql))
{
	foreach (DataRow record in dbdata.Rows)
	{
		writer.StartRow();
		foreach (DataColumn col in dbdata.Columns) // 每个单元格
		{
			var colval = record[col];
			if (DBNull.Value.Equals(record[col])) { colval = DBNull.Value; }
			var colldbtype = col.DataType.Name.ToString();
			NpgsqlDbType pgtype = NpgsqlDbType.Varchar;

	// 最好不要使用自动识别默认数据格式,而是自定义每个栏位对应的数据格式
		  //  if (colldbtype.ToLower().Contains("int64") || colldbtype.ToLower().Contains("int32")) { pgtype = NpgsqlDbType.Bigint; }
	//  if (colldbtype.ToLower().Contains("decimal")) { pgtype = NpgsqlDbType.Numeric; } 
	 //  if (colldbtype.ToLower().Contains("double")) { pgtype = NpgsqlDbType.Double; }
	 // if (colldbtype.ToLower().Contains("string")) { pgtype = NpgsqlDbType.Varchar; }

			string[] charList = { "producttype", "factoryname", "productspecname", "productrequestname", "productquantity", "createuser", "instruction", "lasteventtimekey" };
			string[] intList = { "planquantity", "process_qty", "scrap_qty", "pickingquantity", "finishedquantity", "output_qty", "no_wms_qty", "operate_date" };
			string[] dblList = { "output_rate", "yield_rate", "finish_rate" };
			string[] tmList = { "createtime", "trackintime", "packagetime", "lasteventtime" };
			if (charList.Contains(col.ToString()) )
			{
				if (!DBNull.Value.Equals(colval))
				{
					colval = colval.ToString();
				}
				pgtype = NpgsqlDbType.Varchar;
			}
			if (intList.Contains(col.ToString()) )
			{
				pgtype = NpgsqlDbType.Integer;
			}
			if (dblList.Contains(col.ToString()))
			{
				if (!DBNull.Value.Equals(colval))
				{
					colval = Convert.ToDouble(colval);
				}
				pgtype = NpgsqlDbType.Double;
			}
			if (tmList.Contains(col.ToString()))
			{
				if (!DBNull.Value.Equals(colval))
				{
					DateTime dateTime = (DateTime)colval;
					colval = dateTime.ToUniversalTime();
				}
				pgtype = NpgsqlDbType.TimestampTz;
			}
			writer.Write(colval, pgtype);
		}
	}
	Console.WriteLine($"start2");
	writer.Complete(); // 直接操作数据库
}
Console.WriteLine($"bulk insert success, count( {dbdata.Rows.Count} )");

 9. 问题:Writing values of 'System.DateTimeOffset' is not supported for parameters having NpgsqlDbType 'Timestamp'.

        原因:NpgsqlDbType.Timestamp使用类型错了。

        解决:使用类型是 NpgsqlDbType.TimestampTz。

 10. 问题:Cannot write DateTimeOffset with Offset=08:00:00 to PostgreSQL type 'timestamp with time zone', only offset 0 (UTC) is supported.

        原因:只允许写入UTC时间的DateTimeOffset对象

        解决:用UtcDateTime格式。如:DateTime utcDateTime = yourDateTimeOffset.UtcDateTime;

 11. 问题:error: Cannot write DateTime with Kind=Unspecified to PostgreSQL type 'timestamp with time zone', only UTC is supported. Note that it's not possible to mix DateTimes with different Kinds in an array, range, or multirange.

        原因:postgreDB上的时间栏位用的是timestamptz格式。

        解决:使用ToUniversalTime。

 if (tmList.Contains(col.ToString()))
 {
	 if (!DBNull.Value.Equals(colval))
	 {
		 DateTime dateTime = (DateTime)colval;
		 colval = dateTime.ToUniversalTime();
	 }
	 pgtype = NpgsqlDbType.TimestampTz;
 }
 writer.Write(colval, pgtype);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1914072.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3Ds MAX 2025:创意的翅膀

初识3Ds MAX 2025 在我初次接触3Ds MAX 2025时&#xff0c;仿佛打开了一扇通往无限可能的大门。那时&#xff0c;我还是一个对三维建模充满好奇的初学者&#xff0c;心中怀揣着对未来的憧憬和对艺术的热爱。3Ds MAX 2025的出现&#xff0c;如同一位温柔的导师&#xff0c;带领…

全面解析BPMN、CMMN、DMN与XML

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 全面解析BPMN、CMMN、DMN与XML 前言BPMN&#xff08;业务流程模型与标记法&#xff09;定义与用途…

【昇思25天学习打卡营打卡指南-第二十二天】GAN图像生成

GAN图像生成 模型简介 生成式对抗网络(Generative Adversarial Networks&#xff0c;GAN)是一种生成式机器学习模型&#xff0c;是近年来复杂分布上无监督学习最具前景的方法之一。 最初&#xff0c;GAN由Ian J. Goodfellow于2014年发明&#xff0c;并在论文Generative Adve…

国产口碑最好的骨传导耳机有哪些?优选五大高口碑机型推荐!

作为一名有着多年工作经验的数码测评师&#xff0c;可以说对骨传导耳机或者蓝牙耳机等数码产品有着深入的了解&#xff0c;近期&#xff0c;有很多粉丝&#xff0c;或者身边的朋友经常向我咨询关于骨传导耳机的问题。确实如此&#xff0c;优质的骨传导耳机能在保护听力、保持环…

AI知识库:以AI之力,引领企业知识管理新纪元

在当今这个信息爆炸的时代&#xff0c;企业面临着前所未有的知识管理挑战。随着数据量的激增&#xff0c;如何高效地整理、存储并快速检索海量信息&#xff0c;成为了每个企业亟需解决的核心问题。 在过去&#xff0c;企业的知识库常常被视为一种必要的负担。它们充满了冗长复…

侯捷C++面向对象高级编程(下)-2-non-explicit one argument constructor

1.构造函数 构造函数: Fraction(int num, int den 1) 初始化分子和分母&#xff0c;允许指定分子 num 和可选的分母 den。默认情况下&#xff0c;分母为 1。 加法运算符重载: Fraction operator(const Fraction& f) 重载了加法运算符 。这使得两个 Fraction 对象可以通过 …

【蓄势·致远】 同为科技(TOWE)2024年年中会议

2024年7月2日-8日&#xff0c;同为科技&#xff08;TOWE&#xff09;召开2024年年中工作会议。会议回顾上半年总体工作情况&#xff0c;分析研判发展形势&#xff0c;规划部署下半年工作。 为期一周的工作会议&#xff0c;由同为科技&#xff08;TOWE&#xff09;创始人、董事长…

vue 画二维码及长按保存

需求 想要做如下图的二维码带文字&#xff0c;且能够长按保存 前期准备 一个canvas安装qrcode&#xff08;命令&#xff1a;npm i qrcode&#xff09; 画二维码及文字 初始化画布 <template><div><canvas ref"canvas" width"300" he…

C# + halcon 联合编程示例

C# halcon 联合编程示例 实现功能 1.加载图像 2.画直线&#xff0c;画圆&#xff0c;画矩形, 画椭圆 ROI&#xff0c;可以调整大小和位置 3.实现找边&#xff0c;找圆功能 效果 开发环境 Visual Studio 2022 .NET Framework 4.8 halcondotnet.dll 查看帮助文档 项目结构 DL…

大模型“聚会”:国内卷价格,国外卷能力

[ GPT-4o和谷歌Gemini不断宣传现阶段AI能力大幅度提高&#xff0c;那么这两家&#xff0c;谁的大模型能力更强呢&#xff1f;这篇文章里&#xff0c;作者就展开了多维度的测试和体验&#xff0c;想了解的同学&#xff0c;可以来看一下。 在中美AI大模型的竞争上&#xff0c;正衍…

CDF累积分布函数和PPF百分点位分布函数

目录 cdf累积分布函数 (CDF) ppf百分位点函数 (PPF) 区别与联系示例关系和区别 cdf 累积分布函数 (CDF) 定义&#xff1a; 累积分布函数 F ( x ) F(x) F(x) 给出随机变量 X X X 小于或等于某个值 x x x 的概率。数学定义&#xff1a; F ( x ) P ( X ≤ x ) F(x) P(X \l…

[C++]——同步异步日志系统(3)

同步异步日志系统 一、日志系统框架设计1.1模块划分1.1.1 日志等级模块1.1.2 日志消息模块1.1.3 日志消息格式化模块1.1.4 日志落地模块&#xff08;日志落地的方向是工厂模式&#xff09;1.1.5 日志器模块&#xff08;日志器的生成是建造者模式&#xff09;1.1.6 异步线程模块…

Coze API接口实战应用

Coze API介绍 概述 Coze API作为Coze平台对外的桥梁&#xff0c;让开发者能够灵活地利用Coze的功能和服务&#xff0c;促进业务流程自动化和系统集成。它覆盖了从数据获取到智能交互的全方位功能&#xff0c;旨在提升工作效率和创造更多可能。 Coze API申请接入流程 1. 发现…

python--实验8 函数(2)

知识点 变量的作用域 定义&#xff1a;解释了局部变量和全局变量的概念。局部变量&#xff1a; 局部变量是在函数内部定义的变量。它们只在该函数内部可见&#xff0c;一旦函数执行完毕&#xff0c;这些变量就会被销毁。例子&#xff1a;在函数内部通过赋值创建的变量。全局…

【卡尔曼滤波】高斯白噪声

生成高斯白噪声并将其应用于信号处理 生成高斯白噪声并将其应用于信号处理 #以下是一个生成高斯白噪声并将其应用于信号处理的示例代码:import numpy as np import matplotlib.pyplot as plt import matplotlib.font_manager ## not work#notice matplotlibrc is a file, not…

hf-mirror (huggingface 的国内镜像)

官网&#xff1a; https://hf-mirror.com/ 网站域名 hf-mirror.com&#xff0c;用于镜像 huggingface.co 域名。作为一个公益项目&#xff0c;致力于帮助国内AI开发者快速、稳定的下载模型、数据集。 如何使用HF-Mirror 方法一&#xff1a;网页下载 在https://hf-mirror.com/…

ubuntu笔记本X86安装nomachine客户端

资源下载: 链接: link 一、首先下载文件 nomachine_8.2.3_4_x86_64.tar.gz到桌面。 二、打开终端,依次输入 进入root模式,需要输入密码,密码不可见。 sudu su复制nomachine_8.2.3_4_x86_64.tar.gz粘贴到/usr目录: cp -r nomachine_8.2.3_4_x86_64.tar.gz /usr进入

使用Godot4组件制作竖版太空射击游戏_2D卷轴飞机射击-敌机配置(五)

文章目录 开发思路敌人节点场景绿色敌人制作 使用Godot4组件制作竖版太空射击游戏_2D卷轴飞机射击&#xff08;一&#xff09; 使用Godot4组件制作竖版太空射击游戏_2D卷轴飞机射击-激光组件&#xff08;二&#xff09; 使用Godot4组件制作竖版太空射击游戏_2D卷轴飞机射击-飞船…

强化学习总结(有具体代码实现)

文章目录 第一部分 强化学习基础第1章 强化学习概述1.1 强化学习概念1.2 强化学习的环境1.3 强化学习的目标1.4 强化学习的数据 第2章 多臂老虎机问题&#xff08;MAB问题&#xff09;2.1 问题描述2.1.1 问题定义2.1.2 形式化描述2.1.3 累积懊悔2.1.4 估计期望奖励 2.2 解决方法…

(自用)gtest单元测试

gtest是Google的一套用于编写C测试的框架&#xff0c;可以运行在很多平台上&#xff08;包括Linux、Mac OS X、Windows、Cygwin等等&#xff09;。基于xUnit架构。支持很多好用的特性&#xff0c;包括自动识别测试、丰富的断言、断言自定义、死亡测试、非终止的失败、生成XML报…