Backend - C# 操作PostgreSQL DB

目录

一、安装 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);//将数据填充到dataTablevar dataTable = new DataTable();npgsqlDataAdapter.Fill(dataTable);//-------------------------插入Target DB(批量)//第1种:插入写死的测试数据,即直接插入的完整sqlNpgsqlCommand 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 使用DataTablevar 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 使用DataSetConsole.WriteLine();var dataSet = new DataSet();npgsqlDataAdapter.Fill(dataSet);//将数据填充到dataSetvar dataTable2 = new DataTable();dataTable2 = dataSet.Tables[0]; //将dataSet的table数据填充到dataTableforeach (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);//将数据填充到dataTableforeach (DataRow dataTableRow in dataTable.Rows){sqlBuilder.AppendFormat(" WHEN {0} THEN {1} ", dataTableRow["bid"], dataTableRow["price"]); // 条件是bid,值是pricesqlBuilder2.AppendFormat(" WHEN {0} THEN \'{1}\' ", dataTableRow["bid"], dataTableRow["name"]); // 条件是bid,值是namesqlBuilder3.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.mzph.cn/news/869657.shtml

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

相关文章

[高频SQL50题(基础版)]第五百八十四题,寻找用户推荐人

题目&#xff1a; 表: Customer ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | | referee_id | int | ---------------------- 在 SQL 中&#xff0c;id 是该表的主键列。 该表的每一…

儿童房灯具什么牌子好?几款儿童房灯具款式墙裂分享

随着科技的不断发展和生活方式的改变&#xff0c;儿童青少年近视率的增长趋势引起了人们的关注。近视不仅对孩子们的视力健康构成威胁&#xff0c;还可能对他们的学习和日常生活带来不便。因此&#xff0c;如何有效地预防和改善儿童青少年的视力问题成为了一个亟待解决的课题。…

2024学生党蓝牙耳机什么牌子好?品牌高性价比蓝牙耳机推荐

2024年&#xff0c;对于追求性价比和品质的学生党来说&#xff0c;选择一款合适的蓝牙耳机是提升学习和生活品质的重要一环。面对市场上琳琅满目的蓝牙耳机产品&#xff0c;2024学生党蓝牙耳机什么牌子好&#xff1f;如何找到既满足音质需求又具备高性价比的款式呢&#xff1f;…

高考后的IT专业启航:暑期预习指南与学习路线图

文章目录 每日一句正能量前言&#xff1a;启航IT世界&#xff0c;高考后的暑期学习之旅基础课程预习指南基础课程预习指南&#xff1a;构建你的IT知识大厦引言一、计算机科学导论二、编程语言入门三、操作系统基础四、数据结构与算法五、网络基础六、数据库原理结语 技术学习路…

02STM32软件安装新建工程

STM32软件安装&新建工程 1.软件安装&#xff1a;1.1Keil5 MDK安装1.2安装器件支持包离线安装支持包在线安装支持包 1.3软件注册&#xff1a;1.4安装驱动STLINK驱动JLink驱动在此文件夹下USB转串口 2.新建工程2.1STM32开发方式&#xff1a;1.寄存器2.标准库3.HAL库 固件库压…

Nginx访问日志按天拆分

使用 logrotate 来实现 如果系统没有安装logrotate 可以使用 sudo yum install logrotate -y 进行安装 配置 logrotate 接下来我们就来配置 nginx 切割的配置文件&#xff0c;我的 nginx 日志路径在/var/log/nginx 我们在 /etc/logrotate.d/ 目录下新建一个 nginx 的文件…

C++ Primer 总结索引 | 第十六章:模板与泛型编程

1、面向对象编程&#xff08;OOP&#xff09;和泛型编程 都能处理在编写程序时 不知道类型的情况。不同之处在于&#xff1a;OOP 能处理类型 在程序运行之前都未知的情况&#xff1b;而在泛型编程中&#xff0c;在编译时就能获知类型了 2、容器、迭代器 和 算法 都是泛型编程的…

【热梗案例】知识点阶段性综合汇总

文章目录 渲染对象、实现统计功能实现删除功能设置发布按钮实现发布按钮的提交功能 直接用CSS的模板&#xff0c;模板代码如下&#xff1a; <template><view class"title">近期热梗</view><view class"out"> <view class&qu…

全面解析BPMN、CMMN、DMN与XML

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

[数据结构] 基于插入的排序 插入排序希尔排序

标题&#xff1a;[数据结构] 排序#插入排序&希尔排序 水墨不写bug 目录 &#xff08;一&#xff09;插入排序 实现思路&#xff1a; 插入排序实现&#xff1a; &#xff08;二&#xff09;希尔排序 希尔排序的基本思想&#xff1a; 希尔排序的实现&#xff1a; 正…

MybatisPlus 多数据源 @DS 选择深入源码理解原理

文章目录 MybatisPlus 多数据源 DS 选择深入源码理解原理 MybatisPlus 多数据源 DS 选择深入源码理解原理 数据源的选择&#xff0c;拦截器为DynamicDataSourceAnnotationInterceptor 这里利用了一个MethodInterceptor接口&#xff0c;我们看看&#xff0c;我们可以看到这个包…

防御笔记第四天(持续更新)

1.状态检测技术 检测数据包是否符合协议的逻辑顺序&#xff1b;检查是否是逻辑上的首包&#xff0c;只有首包才会创建会话表。 状态检测机制可以选择关闭或则开启 [USG6000V1]firewall session link-state tcp ? check Indicate link state check [USG6000V1]firewall ses…

CLion学习笔记-cmake编译和多main函数编译

这里就不讲怎么配置clion了 项目名字 pcl_kdtree_search 1.新建一个工程名字自己取&#xff0c;我这里用自己学习pcl的&#xff0c;加一个main函数&#xff0c;这个时候Cmake里边就是这样的。 #声明要求的cmake最低版本 cmake_minimum_required(VERSION 3.19) #声明一个工程…

消息称台积电下周开始试产 2nm 芯片,有望率先用于苹果 iPhone 17

消息称台积电下周开始试产 2nm 芯片&#xff0c;有望率先用于苹果 iPhone 17 &#x1f4a1;&#x1f4f1; 大家好&#xff0c;我是猫头虎&#xff0c;科技自媒体博主 &#x1f431;&#x1f42f;&#xff0c;带你洞察科技世界的每一个细节&#xff01;&#x1f525; 关于猫头…

sklearn(Python机器学习库)介绍

0 引言 Sklearn (全称 Scikit-Learn)是基于Python 编程语言的免费软件机器学习库。 Scikit-learn主要是用Python编写的,它建立在 NumPy, SciPy, Pandas 和 Matplotlib 之上,里面API 的设计非常好,所有对象的接口简单,很适合新手上路。 Scikit-learn与许多其他Python库很好地…

MAT(Eclipse Memory Analyzer) Windows安装

MAT&#xff08;Eclipse Memory Analyzer&#xff09; Windows安装 MAT&#xff08;Eclipse Memory Analyzer&#xff09;是一个Java的内存分析工具 MAT下载地址 安装完成之后的目录机构 如若出现java版本过低的解决办法 在配置文件MemoryAnalyzer.ini中添加指定Java的版本…

PD协议诱骗芯片,XSP08Q,XSP16应用笔记

XSP08Q是3C数码或小家电产品的Type-C接口控制芯片&#xff0c;它负责和PD充电器通讯&#xff0c;获取充电器的快充电压档位&#xff0c;如5V4A&#xff0c;9V3A&#xff0c;12V2A&#xff0c;15V3A&#xff0c;20V5A等等。 XSP08Q支持PD协议&#xff0c;BC1.2协议&#xff0c;Q…

从产业链视角审视工作

从产业链视角审视工作&#xff1a;定位、价值与成长 作为一名技术博客博主&#xff0c;我经常收到各种关于职业发展、技术成长和学习路径的问题。最近&#xff0c;我看了一份学习报告&#xff0c;其中提到了一种非常有趣且实用的视角——从产业链的角度去审视自己的工作。这种视…

Web 自动化测试主流框架都有哪些?

Web移动端自动化测试成为了现代软件开发流程中的重要环节&#xff0c;因此&#xff0c;很多主流框架被开发出来来帮助开发人员提高测试效率。本篇文章将从零到一详细介绍Web移动端自动化测试的主流框架。 一、Web移动端自动化测试框架简介 Web移动端自动化测试框架是一种开发工…

百元平价蓝牙耳机哪款好?平价高性价比蓝牙耳机推荐

随着蓝牙耳机的普及&#xff0c;市面上各种品牌的蓝牙耳机也层出不穷。对于那些预算在百元平价的朋友来说&#xff0c;百元平价蓝牙耳机哪款好&#xff1f;这个问题就显得格外重要了。毕竟&#xff0c;蓝牙耳机作为日常生活中不可或缺的小伙伴&#xff0c;不仅需要音质出众、续…