储存过程

概述

存储过程是由流控制和SQL语句书写的过程,这个过程经编译和优化后存储在数据库服务器中,应用程序使用时只要调用即可; 相对于SQL语句,它为用户提供了对数据更为方便的检索和更新方式.存储过程一般都是多条语句一起执行,所以会减少网络的开销.

存储过程和其他SQL语句的使用类似,只需要在执行命令 OscarCommand 之前,设置命令类型 CommandTypeCommandType.StoredProcedure 这是必须的.这样驱动程序才会将这个SQL语句作为存储过程名来处理.

存储过程的参数的 Direction 属性为枚举值 ParameterDirection.

ParameterDirection有四个值,分别为 Input , Output , InputOutput , ReturnValue.

  • Input 类型的参数:参数值通过命令对象,传递给存储过程,驱动不会更改该参数的值.
  • Output 类型的参数:参数的值可以为Null,也可以是任何其他类型的值,驱动不会将该类型的值给存储过程,而是将相同位置的参数在存储过程中获得值,返回给用户.
  • InputOutput 类型的参数:该类型的参数的值传递给存储过程,并且接收改变后的值.
  • ReturnValue 类型的参数:参数获得存储过程执行后得到的值.

在 PROVIDER 中调用已储存过程的语法如下所示。

{过程名[(@ParametersName1, @ParametersName2, ...)]}

不带参数的储存过程的语法类似:

{过程名()}

这里无论带不带参数的存储过程的命令调用时,过程名后的圆括号不是必须的,例如: 有一个名为funcC的存储过程名,带有一个 inputoutput 参数,并且返回值为参数值减 3. 我们在创建命令对象 OscarCommand 对象时,可以采用如下的方法创建.

OscarCommand command = new OscarCommand("funcC", TheConnection);

OscarCommand command = new OscarCommand("funcC(@a)", TheConnection);

OscarCommand command = new OscarCommand("funcC(:a)", TheConnection);

以上三种方式创建的存储过程命令都是合法的,其中,第一种没有括号,也没有给出参数名,但是需要在后面的代码中,添加一个参数给命令对象,否则会抛出异常.

示例 1

private void TestCreateProcedureMethod()
{
    var command = _connect.CreateCommand();

    command.CommandText = "CREATE OR REPLACE PROCEDURE PROC000_000(INT, VARCHAR(64)) AS BEGIN INSERT INTO ProcTestTable VALUES($1, $2);END;";

    try
    {
        var result = command.ExecuteReader();
    }
    catch (Exception e)
    {
        Assert.Fail(message: e.Message);
    }
}

[TestMethod]
public void TestExecuteProcedureMethod()
{
    TestCreateProcedureMethod();
    var command = _connect.CreateCommand();
    command.CommandType = System.Data.CommandType.StoredProcedure;

    command.CommandText = "PROC000_000(@v1,@v2)";

    var param1 = new OscarParameter("v1", OscarDbType.Int);

    param1.Direction = System.Data.ParameterDirection.Input;
    param1.Value = 13;

    command.Parameters.Add(param1);

    var param2 = new OscarParameter("v2", OscarDbType.VarChar);

    param2.Direction = System.Data.ParameterDirection.Input;
    param2.Value = "100";

    command.Parameters.Add(param2);

    try
    {
        var result = command.ExecuteReader();
    }
    catch (Exception e)
    {
        Assert.Fail(message: e.Message);
    }
    DropProcecureMethod("PROC000_000");
}

private void DropProcecureMethod(string name)
{
    var command = _connect.CreateCommand();

    command.CommandText = $"DROP PROCEDURE {name} CASCADE;";

    try
    {
        var result = command.ExecuteNonQuery();
    }
    catch (Exception e)
    {
        Assert.Fail(message: e.Message);
    }
}

示例 2

private void TestCreateProcedureMethod1()
{
    var command = _connect.CreateCommand();

    command.CommandText = "CREATE OR REPLACE PROCEDURE BEGINPROC_0 (v1 OUT INTEGER,v2 IN INTEGER) AS BEGIN SELECT COUNT(*) INTO v1 FROM ProcTestTable WHERE ID=v2;END;";

    try
    {
        var result = command.ExecuteReader();
    }
    catch (Exception e)
    {
        Assert.Fail(message: e.Message);
    }
}

[TestMethod]
public void TestExecuteProcedureMethod2()
{
    TestCreateProcedureMethod1();
    var command = _connect.CreateCommand();
    command.CommandType = System.Data.CommandType.StoredProcedure;

    command.CommandText = "BEGINPROC_0 (@v1,@v2)";

    var param1 = new OscarParameter("v1", OscarDbType.Int);
    param1.Value = 1;

    param1.Direction = System.Data.ParameterDirection.Output;

    command.Parameters.Add(param1);

    var param2 = new OscarParameter("v2", OscarDbType.Int);

    param2.Direction = System.Data.ParameterDirection.Input;
    param2.Value = 11;

    command.Parameters.Add(param2);

    try
    {
        var result = command.ExecuteReader();
    }
    catch (Exception e)
    {
        Assert.Fail(message: e.Message);
    }
    DropProcecureMethod("BEGINPROC_0");
}

private void DropProcecureMethod(string name)
{
    var command = _connect.CreateCommand();

    command.CommandText = $"DROP PROCEDURE {name} CASCADE;";

    try
    {
        var result = command.ExecuteNonQuery();
    }
    catch (Exception e)
    {
        Assert.Fail(message: e.Message);
    }
}
引用