一、相比于在程序当中写sql语句的数据库开发方式,存储过程是有很多优势的,其中最突出的两点:
1、将程序的与数据库从架构上面相互分离,但需求变化的时候,比如说原来查询字段a,但是后来突然改变要去查询字段a、b--我们直接改写存储过程就可以了,不需要去改变程序。
2、存储过程会在数据库做缓存,就是说在客户端访问一次过后,请求查询的结果会被缓存下来,对于大并发量的产品是有很多好处的
二、下面我以.net例子编写简单的存储过程的例子:
1. 只返回单一记录集的存储过程
新建一个网站
把配置文件Web.config改写如下
<connectionStrings>
<add name="TestConnectionString" connectionString="Data Source=127.0.0.1;Initial Catalog=TestDemo;Persist Security Info=True;User ID=sa;Password=qs@123456" providerName="System.Data.SqlClient"/>
</connectionStrings>
在数据库下建一个表:Categories(phoneModel,phoneTest)
存一些值
创建存储过程:
这是通过sql语句去创建
CREATE PROCEDURE Categoriestest1
AS
select *
from Categories
GO
之后我们可以看到如下的存储过程
在Default.aspx页面下面,
加入如下控件
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
在Default.aspx.cs
添加入下代码:
protected void Page_Load(object sender, EventArgs e)
{
fillGridView();
}
public void fillGridView() {
SqlConnection sqlconn = new SqlConnection(conn);
SqlCommand cmd = new SqlCommand();
// 设置sql连接
cmd.Connection = sqlconn;
// 如果执行语句
cmd.CommandText = "Categoriestest1";
// 指定执行语句为存储过程
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter dp = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
// 填充dataset
dp.Fill(ds);
// 以下是显示效果
GridView1.DataSource = ds;
GridView1.DataBind();
}
跑一下,得到如下的结果
2. 没有输入输出的存储过程
改上例中的表结构为
建立如下的存储过程
CREATE PROCEDURE Categoriestest2 AS
insert into dbo.Categories
(CategoryName,Description,Picture)
values ('test1','test1',null)
GO
在Default.aspx页面中,拖入控件
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
在Default.aspx.cs文件中添加如下的代码:
protected void Page_Load(object sender, EventArgs e)
{
fillGridView();
}
public void fillGridView() {
SqlConnection sqlconn = new SqlConnection(conn);
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlconn;
cmd.CommandText = "Categoriestest2";
cmd.CommandType = CommandType.StoredProcedure;
sqlconn.Open();
// 执′行D并¢显?示?影?响ì行D数簓
Label1.Text = cmd.ExecuteNonQuery().ToString();
sqlconn.Close();
}
3. 有返回值的存储过程
存储过程:
CREATE PROCEDURE Categoriestest3
AS
insert into dbo.Categories
(CategoryName,[Description],[Picture])
values ('test1','test1',null)
return @@rowcount
GO
C#代码:
protected void Page_Load(object sender, EventArgs e)
{
fillGridView();
}
public void fillGridView() {
SqlConnection sqlconn = new SqlConnection(conn);
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlconn;
cmd.CommandText = "Categoriestest3";
cmd.CommandType = CommandType.StoredProcedure;
// 创建参数
IDataParameter[] parameters = {
new SqlParameter("rval", SqlDbType.Int,4)
};
// 将参数类型设置为 返回值类型
parameters[0].Direction = ParameterDirection.ReturnValue;
// 添加参数
cmd.Parameters.Add(parameters[0]);
sqlconn.Open();
// 执行存储过程并返回影响的行数
Label1.Text = cmd.ExecuteNonQuery().ToString();
sqlconn.Close();
// 显示影响的行数和返回值
Label1.Text += "-" + parameters[0].Value.ToString() ;}
4. 有输入参数和输出参数的存储过程
表:
存储过程:
CREATE PROCEDURE Categoriestest4
@id int output,
@CategoryName nvarchar(15)
AS
insert into dbo.Categories
(CategoryName,Description,Picture)
values (@CategoryName,'test1',null)
set @id = @@IDENTITY
GO
C#代码:
protected void Page_Load(object sender, EventArgs e)
{
fillGridView();
}
public void fillGridView() {
string conn = ConfigurationManager.ConnectionStrings["TestConnectionString"].ConnectionString;
SqlConnection sqlconn = new SqlConnection(conn);
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlconn;
cmd.CommandText = "Categoriestest4";
cmd.CommandType = CommandType.StoredProcedure;
// 创建参数
IDataParameter[] parameters = {
new SqlParameter("@Id", SqlDbType.Int,4) ,
new SqlParameter("@CategoryName", SqlDbType.NVarChar,15) ,
};
// 设置参数类型
parameters[0].Direction = ParameterDirection.Output; // 设置为输出参数
parameters[1].Value = "testCategoryName";
// 添加参数
cmd.Parameters.Add(parameters[0]);
cmd.Parameters.Add(parameters[1]);
sqlconn.Open();
// 执行存储过程并返回影响的行数
Label1.Text = cmd.ExecuteNonQuery().ToString();
sqlconn.Close();
// 显示影响的行数和输出参数
Label1.Text += "-" + parameters[0].Value.ToString();
}
5. 同时具有返回值、输入参数、输出参数的存储过程
存储过程:
CREATE PROCEDURE Categoriestest5
@id int output,
@CategoryName nvarchar(15)
AS
insert into dbo.Categories
(CategoryName,Description,Picture)
values (@CategoryName,'test1',null)
set @id = @@IDENTITY
return @@rowcount
GO
C#代码:
protected void Page_Load(object sender, EventArgs e)
{
fillGridView();
}
public void fillGridView() {
string conn = ConfigurationManager.ConnectionStrings["TestConnectionString"].ConnectionString;
SqlConnection sqlconn = new SqlConnection(conn);
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlconn;
cmd.CommandText = "Categoriestest5";
cmd.CommandType = CommandType.StoredProcedure;
// 创建参数
IDataParameter[] parameters = {
new SqlParameter("@Id", SqlDbType.Int,4) ,
new SqlParameter("@CategoryName", SqlDbType.NVarChar,15) ,
new SqlParameter("rval", SqlDbType.Int,4)
};
// 设置参数类型
parameters[0].Direction = ParameterDirection.Output; // 设置为输出参数
parameters[1].Value = "testCategoryName"; // 给输入参数赋值
parameters[2].Direction = ParameterDirection.ReturnValue; // 设置为返回值
// 添加参数
cmd.Parameters.Add(parameters[0]);
cmd.Parameters.Add(parameters[1]);
cmd.Parameters.Add(parameters[2]);
sqlconn.Open();
// 执行存储过程并返回影响的行数
Label1.Text = cmd.ExecuteNonQuery().ToString();
sqlconn.Close();
// 显示影响的行数,输出参数和返回值
Label1.Text += "-" + parameters[0].Value.ToString() + "-" + parameters[2].Value.ToString();
}
6. 同时返回参数和记录集的存储过程
存储过程Categoriestest6
CREATE PROCEDURE Categoriestest6
@id int output,
@CategoryName nvarchar(15)
AS
insert into dbo.Categories
(CategoryName,[Description],[Picture])
values (@CategoryName,'test1',null)
set @id = @@IDENTITY
select * from Categories
return @@rowcount
GO
C#代码:
protected void Page_Load(object sender, EventArgs e)
{
fillGridView();
}
public void fillGridView() {
string conn = ConfigurationManager.ConnectionStrings["TestConnectionString"].ConnectionString;
SqlConnection sqlconn = new SqlConnection(conn);
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlconn;
cmd.CommandText = "Categoriestest6";
cmd.CommandType = CommandType.StoredProcedure;
// 创建参数
IDataParameter[] parameters = {
new SqlParameter("@Id", SqlDbType.Int,4) ,
new SqlParameter("@CategoryName", SqlDbType.NVarChar,15) ,
new SqlParameter("rval", SqlDbType.Int,4)
// 返回值
};
// 设置参数类型
parameters[0].Direction = ParameterDirection.Output;
// 设置为输出参数
parameters[1].Value = "testCategoryName";
// 给输入参数赋值
parameters[2].Direction = ParameterDirection.ReturnValue;
// 设置为返回值
// 添加参数
cmd.Parameters.Add(parameters[0]);
cmd.Parameters.Add(parameters[1]);
cmd.Parameters.Add(parameters[2]);
SqlDataAdapter dp = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
// 填充dataset
dp.Fill(ds);
// 显示结果集
GridView1.DataSource = ds.Tables[0];
GridView1.DataBind();
Label1.Text = "";
// 显示输出参数和返回值
Label1.Text += parameters[0].Value.ToString() + "-" + parameters[2].Value.ToString();
}
7. 返回多个记录集的存储过程
存储过程7
CREATE PROCEDURE Categoriestest7
AS
select * from Categories
select * from Categories
GO
C#代码:
protected void Page_Load(object sender, EventArgs e)
{
fillGridView();
}
public void fillGridView() {
string conn = ConfigurationManager.ConnectionStrings["TestConnectionString"].ConnectionString;
SqlConnection sqlconn = new SqlConnection(conn);
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlconn;
cmd.CommandText = "Categoriestest7";
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter dp = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
// 填充dataset
dp.Fill(ds);
// 显示结果集1
GridView1.DataSource = ds.Tables[0];
GridView1.DataBind();
// 显示结果集2
GridView2.DataSource = ds.Tables[1];
GridView2.DataBind();
}
Default.aspx:
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
<asp:GridView ID="GridView2" runat="server">
</asp:GridView>
JDBC存储过程调用方式(ps:在lib目录下放sqlserver的驱动)
JDBC调用存储过程也是有四种情况:
本文主要是总结 如何实现 JDBC调用SQLSERVER的存储过程,从以下情况分别介绍:
[1]、只有输入IN参数,没有输出OUT参数
[2]、既有输入IN参数,也有输出OUT参数,输出是简单值(非列表)
[3]、既有输入IN参数,也有输出OUT参数,输出是列表
[4]、输入输出参数是同一个(IN OUT)
【准备工作】
创建一个测试表TMP_MICHAEL ,并插入数据,SQL如下:
create table TMP_MICHAEL
(
USER_ID VARCHAR(20),
USER_NAME VARCHAR(10),
SALARY decimal(8,2),
OTHER_INFO VARCHAR(100)
)
insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
values ('michael', 'Michael', 5000, 'http://sjsky.iteye.com');
insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
values ('zhangsan', '张三', 10000, null);
insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
values ('aoi_sola', '苍井空', 99999.99, 'twitter account');
insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
values ('李四', '李四', 2500, null);
SQL SERVER jdbc 常量:
private final static String DB_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private final static String DB_CONNECTION = "jdbc:sqlserver://127.0.0.1:1433;DatabaseName=TestDemo";
private final static String DB_NAME = "sa";
private final static String DB_PWd = "qs@123456";
[一]、只有输入IN参数,没有输出OUT参数
CREATE PROCEDURE TEST_MICHAEL_NOOUT
@USER_ID VARCHAR(20),
@USER_NAME VARCHAR(10),
@SALARY decimal(8,2),
@OTHER_INFO VARCHAR(100)
as
insert into dbo.TMP_MICHAEL
(USER_ID,USER_NAME,SALARY,OTHER_INFO)
values (@USER_ID,@USER_NAME,@SALARY,@OTHER_INFO)
Go
TmpMichael.java类
package dao;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
public class TmpMichael {
//参数
private final static String DB_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private final static String DB_CONNECTION = "jdbc:sqlserver://127.0.0.1:1433;DatabaseName=TestDemo";
private final static String DB_NAME = "sa";
private final static String DB_PWd = "qs@123456";
//调用函数
public static void testProcNoOut() throws Exception {
System.out.println("------- start 测试调用存储过程:无返回值");
Connection conn = null;
CallableStatement callStmt = null;
try {
Class.forName(DB_DRIVER);
conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);
// 存储过程 TEST_MICHAEL_NOOUT 其实是向数据库插入一条数据
callStmt = conn.prepareCall("{call TEST_MICHAEL_NOOUT(?,?,?,?)}");
// 参数index从1开始,依次 1,2,3...
callStmt.setString(1, "jdbc");
callStmt.setString(2, "JDBC");
callStmt.setDouble(3, 8000.00);
callStmt.setString(4, "http://sjsky.iteye.com");
callStmt.execute();
System.out.println("------- Test End.");
} catch (Exception e) {
e.printStackTrace(System.out);
} finally {
if (null != callStmt) {
callStmt.close();
}
if (null != conn) {
conn.close();
}
}
}
}
在index.jsp页面中添加入下代码
<jsp:useBean id="TmpMichael" class="dao.TmpMichael"></jsp:useBean>
<%
TmpMichael.testProcNoOut();
%>
跑起这个应用:
查看数据库:
调用成功