最近做一个工厂的自动化项目使用到sqlserver,查询其中某个值的时候返回的是空值,研究了一下发现该值的类型是nchar,定长unicode编码,网上查了下nchar
和nvarchar
的区别,nvarchar类型存储字节数为字长实际长度两倍(unicode编码),进一步通过程序验证发现nchar(l)存储时按开辟空间的长度进行存储的(也是unicode编码,字节数为2*l),余位会补空,读取到C#中该值长度是l
而不是实际长度。以下是测试代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Data;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string connectionString = "server=;database=;user=;password=";
using (SqlConnection con = new SqlConnection(connectionString))
{
try
{
con.Open();
}
catch (SqlException e)
{
throw e;
}
if (con.State == ConnectionState.Open)
{
string insertCmd = $"insert into InvoiceCardState(ChrBoxUp,ChrLot) values('KS','KS')";
int rows=ExecuteSql(insertCmd, con);
DataTable dt = new DataTable();
if(rows>0)
{
string queryCmd = $"select * from Test where ChrBoxUp='KS'";
QuerySql(queryCmd, con, dt);
if(dt.Rows.Count>0)
{
string lot = dt.Rows[0]["ChrLot"].ToString();
string pb = dt.Rows[0]["ChrBoxUp"].ToString();
int lotl = lot.Length;
int pbl = pb.Length;
Console.WriteLine("lot length:" + lotl.ToString());
Console.WriteLine("pb length:" + pbl.ToString());
}
}
}
}
}
static int ExecuteSql(string sqlcmd, SqlConnection con)
{
int rows = 0;
SqlCommand cmd = new SqlCommand(sqlcmd, con);
try
{
rows = cmd.ExecuteNonQuery();
}
catch (SqlException e)
{
throw e;
}
return rows;
}
static int QuerySql(string sqlcmd, SqlConnection con, DataTable dt)
{
int errorCode = 0;
SqlCommand cmd = new SqlCommand(sqlcmd, con);
using (SqlDataAdapter adpter = new SqlDataAdapter(cmd))
{
try
{
adpter.Fill(dt);
}
catch (SqlException e)
{
errorCode = e.ErrorCode;
}
}
return errorCode;
}
}
}
其中Test表中ChrBoxUp
为nvarchar(12)
,ChrLot
类型为nchar(12),均存入字段KS
,然后读取,结果ChrLot长度度为12,ChrBoxUp长度为2,加断点监视string lot
的值KS
右端存在一部分空格,并且如果将查询条件改为where ChrLot='KS'
,查询结果为空,如果需要查询可以用where rtrim(ChrLot)='KS'
进行查询。