VastbaseG100

基于openGauss内核开发的企业级关系型数据库。

Menu

执行SQL语句并处理结果

向数据库发出执行SQL的请求时,需要使用NpgsqlCommand实例发出查询,服务端执行完成后将返回一个NpgsqlDataReader实例,该实例包括查询的结果。

执行查询

使用NpgsqlCommand执行查询:

/将返回两个结果集
using (var cmd = new NpgsqlCommand("SELECT ...; SELECT ...",conn))
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// Read first resultset
        }
        reader.NextResult();
        while (reader.Read())
{
// Read second resultset
}
}

读取结果

获取单一结果

执行查询,并返回查询所返回的结果集中第一行的第一列。所有其他的列和行将被忽略。此方法适合使用 ExecuteScalar方法从数据库中检索单个值(例如一个聚合值),比如统计数量。

对于查询单个字段,不包括函数的 select 语句,例如 select a字段 from 表A,如果不存在值, DbCommand.ExecuteScalar 方法的返回值是null,调用者需要使用 result == null 来判断。

对于使用函数的select 语句,例如select sum(a字段) from表A,如果不存在值,DbCommand.ExceuteScalar 方法的返回值是 DBNull.Value,调用者需要用 result is DBNull 或者 result == DBNull.Value来判断。

 string sql = "select count(*) from test";   
using (var cmd = new NpgsqlCommand(sql,conn))
{
int count = Convert.ToInt32(cmd.ExecuteScalar());    //将结果转换成整数
}

使用DataReader获取结果

驱动程序获取某个查询的结果集,并以流的方式返回给客户端。示例:

//将返回两个结果集
using (var cmd = new NpgsqlCommand("SELECT ...; SELECT ...",conn)) 
using (NpgsqlDataReader reader = cmd.ExecuteReader())
{
    while (reader.Read()) 
{
        // Read first resultset
        for (i = 0; i < reader.FieldCount; i++) 
{
            Console.Write("{0} \t", reader[i]); //获得字段名
string  fieldType =  reader.GetFieldType(i).ToString();  //获得指定字段的类型
        }   
        var fieldValue = reader["fieldName"]; // 获得指定字段的值(fieldName是表的某个字段)
}

    reader.NextResult();
    while (reader.Read()) {
        // Read second resultset
       ......
    }
    reader.Close();
}

使用NpgsqlCommand对象

在使用NpgsqlCommand,需要注意以下问题:

NpgsqlCommand传入SQL命令是在构造函数中进行的,因此最好一次执行对应一个NpgsqlCommand实例。为了避免.NET垃圾回收不及时,可以指定空间回收时机使得命令执行完成且结果获取之后释放NpgsqlCommand空间,可以通过using(......)方式或者try-finally来指定:

using (var cmd = new NpgsqlCommand(“......", conn))  
using (NpgsqlDataReader reader = cmd.ExecuteReader()){
    ......
}

或者

var cmd = new NpgsqlCommand(“......");
Try
{
    NpgsqlDataReader reader = cmd.ExecuteReader();
    Try
    {
        ......
    }
    Finally
    {
            if (reader != null)   
                ((IDisposable)reader).Dispose();
    }
}  
Finally
{
    if (cmd != null)   
        ((IDisposable)cmd).Dispose();
}

通过上述两种方式都可以进行及时的空间回收,不会造成空间浪费,并且可以保证使用安全。另外,也可以进行NpgsqlCommand的复用,即可以多次使用一个NpgsqlCommand实例,可以在打开连接时创建NpgsqlCommand然后在连接的整个生命周期内使用它,每次在执行之前可以修改NpgsqlCommand的参数:

cmd.Connection = conn;   //设置连接
cmd.CommandType = CommandType.Text;    //指明命令类型
cmd.CommandText = "selelct * from data";   //SQL语句
NpgsqlDataReader reader = cmd.ExecuteReader();

但是这用方式要注意使用新连接时,要手动断掉旧链接。

  • 如果在处理NpgsqlDataReader 时需要执行查询,可以创建另一个NpgsqlCommand来执行。

  • 如果使用多线程,并且有多个线程正在使用数据库,则每个线程必须使用单独的NpgsqlCommand.,建议每个命令使用单独的NpgsqlCommand,保证安全。

  • 使用完NpgsqlCommand应该及时释放空间,以及及时断开连接。

使用NpgsqlDataReader对象

使用NpgsqlDataReader 接口时必须考虑下面的问题:

  • NpgsqlDataReader对象是NpgsqlCommand对象在执行SQL语句后返回的一个结果对象,当结果集有多个时,默认指向的是第一个结果集,如果要访问下一个结果集时,需要使用NpgsqlDataReader的NextResult方法;在某一个结果集中,通过不断调用NpgsqlDataReader的Read方法,依次获取该结果集的一条记录,构建NpgsqlDataReader对象的结构,可以通过NpgsqlDataReader下标数字的方法获取字段信息,通过NpgsqlDataReader下标字段名的方法获取值。

  • NpgsqlDataReader的Read方法,保证了对一个结果集的一条记录只访问一次。

  • 在结束对一个 NpgsqlDataReader 的处理后,必须调用close()来关闭它,并及时释放空间。

  • 为了保证使用安全和线程安全,最好是一个NpgsqlCommand对应一个NpgsqlDataReader对象,其实一个NpgsqlDataReader对象就是由NpgsqlCommand执行产生的。当使用那个创建NpgsqlDataReader的 NpgsqlCommand做另一个查询请求, 当前打开的 NpgsqlDataReader实例不会自动关闭,此处小心使用。

执行更新

要更改数据(执行一个insert,update或者delete),可以使用NpgsqlCommand对象的ExecuteNonQuery() 方法.ExecuteNonQuery() 方法类似于发出 select语句的ExecuteReader()方法,不过,它不返回 NpgsqlDataReader ,它返回的是:

  • 对于Update、insert、Delete语句执行成功是返回值为该命令所影响的行数,如果影响的行数是0,则返回值就是0;

  • 对于所有其他类型的语句,返回值为-1;

  • 如果发生回滚,返回值也为-1;

删除

string sql = "delete from test where id=1";   
NpgsqlCommand cmd = new NpgsqlCommand(sql, conn);   
cmd .ExecuteNonQuery();   

更新

string sql = "update test set price=300 where id=1";   
NpgsqlCommand cmd = new NpgsqlCommand(sql, conn);   
cmd .ExecuteNonQuery();

插入

插入单行:

string sql = "insert into test values (1,200)";   
NpgsqlCommand cmd = new NpgsqlCommand(sql, conn);   
cmd .ExecuteNonQuery(); 

其中,SQL语句的参数,可以通过格式化字符串的方式去设置与替换,这是最简单的调用方式。当然也可以使用指定参数的方式去调用,后面存储过程一节会介绍这种方式。

创建或修改数据库对象

要创建、更改或者删除一个类似表或者视图这样的数据库对象, 仍然可以使用ExecuteNonQuery() 方法,但是返回值只返回-1。

例如DROP表:

string sql = "DROP TABLE mytable";   
NpgsqlCommand cmd = new NpgsqlCommand(sql, conn);   
cmd .ExecuteNonQuery(); 

DROP数据库:

string sql = "DROP DATABASE mydatabase";   
NpgsqlCommand cmd = new NpgsqlCommand(sql, conn);   
cmd .ExecuteNonQuery(); s

小结

总结来说,SQL语句的主要执行对象就是NpgsqlCommand对象,只不过具体的执行过程不同,针对查询功能,调用的是NpgsqlCommand. ExecuteScalar功能或者NpgsqlCommand.ExecuteReader功能,查询返回的结果会返回一个NpgsqlDataReader对象,可以从这个对象里去获取数据;而其它类型的SQL,则使用NpgsqlCommand.ExecuteNonQuery功能,在针对数据记录的增删改操作,会返回受影响的记录数量,其它操作比如针对数据库对象的操作,返回-1。