11-调用存储过程

数据表及数据准备:

create table Member
(
    MemberId int primary key identity(1,1),
    MemberAccount nvarchar(20) unique,
    MemberPwd nvarchar(20),
    MemberName nvarchar(20),
    MemberPhone nvarchar(20)
)
truncate table Member

insert into Member(MemberAccount,MemberPwd,MemberName,MemberPhone)
values('liubei','123456','刘备','4659874564')
insert into Member(MemberAccount,MemberPwd,MemberName,MemberPhone)
values('guanyu','123456','关羽','42354234124')
insert into Member(MemberAccount,MemberPwd,MemberName,MemberPhone)
values('zhangfei','123456','张飞','41253445')
insert into Member(MemberAccount,MemberPwd,MemberName,MemberPhone)
values('zhangyun','123456','赵云','75675676547')
insert into Member(MemberAccount,MemberPwd,MemberName,MemberPhone)
values('machao','123456','马超','532523523')

本文以下内容都借助于前面封装的DBHelper类

一、调用exec语句执行存储过程

由于在SQL SERVER内部调用存储过程使用的方式是:

exec 存储过程名 参数1,参数2,参数3...

所以我们可以在C#中调用exec的sql语句,让此sql语句去调用存储过程,严格来说,此种方式并不能称之为C#调用存储过程,本质上仍然是调用的sql语句。

示例:

0044.PNG

0045.PNG

需求:采用调用存储过程的方式实现数据的显示以及数据的新增。

主要代码:

SQL存储过程代码:

--查询Member表所有数据的存储(没有参数)
create proc procSelectMember
as
    select * from Member
go
exec procSelectMember

--添加会员信息(有输入参数)
create proc procInsertMember
    @acc nvarchar(20),
    @pwd nvarchar(20),
    @memName nvarchar(20),
    @memPhone nvarchar(20)
as
    insert into Member(MemberAccount,MemberPwd,MemberName,MemberPhone)
    values(@acc,@pwd,@memName,@memPhone)
go
exec procInsertMember 'sunwukong','123456','孙悟空','13554856985'

数据显示C#代码:

private void BindData()
{
    DBHelper.PrepareSql("exec procSelectMember");
    this.dataGridView1.DataSource = DBHelper.ExecQuery();
}
private void Form1_Load(object sender, EventArgs e)
{
    BindData();
}

数据新增C#代码:

private void btAdd_Click(object sender, EventArgs e)
{
    DBHelper.PrepareSql(string.Format("exec procInsertMember '{0}','{1}','{2}','{3}'"
        ,this.txtAccount.Text,this.txtPwd.Text,this.txtNickName.Text,this.txtPhone.Text));
    DBHelper.ExecNonQuery();
}

二、直接调用存储过程

调用存储过程需要将CommandType执行命令类型设置为CommandType.StoredProcedure存储过程。

(1)调用没有参数的存储过程

0044.PNG

需求:实现数据的显示。

主要代码:

SQL存储过程代码:

--查询Member表所有数据的存储(没有参数)
create proc procSelectMember
as
    select * from Member
go
--调用
exec procSelectMember

为了支持存储过程,给DBHelper添加方法:

public static void PrepareProc(string sql)
{
    OpenConn(); //打开数据库连接
    adp = new SqlDataAdapter(sql, conn);
    adp.SelectCommand.CommandType = CommandType.StoredProcedure;
}

窗体代码:

private void BindData()
{
    DBHelper.PrepareProc("procSelectMember");
    this.dataGridView1.DataSource = DBHelper.ExecQuery();
}
private void Form1_Load(object sender, EventArgs e)
{
    BindData();
}

(2)调用有输入参数的存储过程

0045.PNG

需求:实现数据的新增。

主要代码:

SQL存储过程代码:

--添加会员信息(有输入参数)
create proc procInsertMember
    @acc nvarchar(20),
    @pwd nvarchar(20),
    @memName nvarchar(20),
    @memPhone nvarchar(20)
as
    insert into Member(MemberAccount,MemberPwd,MemberName,MemberPhone)
    values(@acc,@pwd,@memName,@memPhone)
go
--调用
exec procInsertMember 'sunwukong','123456','孙悟空','13554856985'

窗体代码:

private void btAdd_Click(object sender, EventArgs e)
{
    DBHelper.PrepareProc("procInsertMember");
    DBHelper.SetParameter("acc", this.txtAccount.Text);
    DBHelper.SetParameter("pwd",this.txtPwd.Text);
    DBHelper.SetParameter("memName", this.txtNickName.Text);
    DBHelper.SetParameter("memPhone", this.txtPhone.Text);
    DBHelper.ExecNonQuery();
}

(3)调用有输入和输出参数的存储过程

0046.PNG

需求:输入用户名,点击"查询电话"按钮,在下面显示姓名和号码。

主要代码:

SQL存储过程:

--根据账号查询姓名和电话(有输入参数,有输出参数)
create proc procGetInfoByAcc
    @acc nvarchar(20),
    @memName nvarchar(20) output,
    @phone nvarchar(20) output
as
    select @memName = (select MemberName from Member where MemberAccount=@acc)
    select @phone = (select MemberPhone from Member where MemberAccount=@acc)
go
--调用
declare @name nvarchar(20)
declare @phone nvarchar(20)
exec procGetInfoByAcc 'machao',@name output,@phone output
select @name,@phone

为了支持输出参数,给DBHelper添加方法:

/// <summary>
/// 设置输出参数(不指定长度,适合非字符串)
/// </summary>
/// <param name="parameterName">参数名称</param>
/// <param name="dbType">参数类型</param>
public static void SetOutParameter(string parameterName, SqlDbType dbType)
{
    parameterName = "@" + parameterName.Trim();
    SqlParameter parameter = new SqlParameter(parameterName, dbType);
    parameter.Direction = ParameterDirection.Output;
    adp.SelectCommand.Parameters.Add(parameter);
}
/// <summary>
/// 设置输出参数(指定长度,适合字符串)
/// </summary>
/// <param name="parameterName">参数名称</param>
/// <param name="dbType">参数类型</param>
/// <param name="size">参数长度</param>
public static void SetOutParameter(string parameterName, SqlDbType dbType, int size)
{
    parameterName = "@" + parameterName.Trim();
    SqlParameter parameter = new SqlParameter(parameterName, dbType, size);
    parameter.Direction = ParameterDirection.Output;
    adp.SelectCommand.Parameters.Add(parameter);
}
/// <summary>
/// 获取参数内容值
/// </summary>
/// <param name="parameterName">参数名称</param>
/// <returns>参数值</returns>
public static object GetParameter(string parameterName)
{
    parameterName = "@" + parameterName.Trim();
    return adp.SelectCommand.Parameters[parameterName].Value;
}

窗体代码:

private void btSearch_Click(object sender, EventArgs e)
{
    DBHelper.PrepareProc("procGetInfoByAcc");
    DBHelper.SetParameter("acc", this.txtAccount.Text);
    DBHelper.SetOutParameter("memName", SqlDbType.NVarChar, 20);
    DBHelper.SetOutParameter("phone", SqlDbType.NVarChar, 20);
    DBHelper.ExecNonQuery();
    this.lblName.Text = "姓名:" + DBHelper.GetParameter("memName").ToString();
    this.lblPhone.Text = "电话:" + DBHelper.GetParameter("phone").ToString();
}

(4)调用有输入输出参数的存储过程

0047.PNG

需求:密码升级,传入用户名和密码;如果用户名密码正确,并且密码长度<8,自动升级成8位密码。

主要代码:

SQL存储过程(SQLSERVER中output参数直接传入值即可以做输入参数,也可以做输出参数):

--密码升级,传入用户名和密码,如果用户名密码正确,并且密码长度<8,自动升级成8位密码
--有输入输出参数(密码作为输入参数也作为输出参数)
select FLOOR(RAND()*10) --0-9之间随机数
create proc procPwdUpgrade
@acc nvarchar(20),
@pwd nvarchar(20) output
as
    if not exists(select * from Member where MemberAccount=@acc and MemberPwd=@pwd)
        set @pwd = ''
    else
    begin
        if len(@pwd) < 8
        begin
            declare @len int = 8- len(@pwd)
            declare @i int = 1
            while @i <= @len
            begin
                
                set @pwd = @pwd + cast(FLOOR(RAND()*10) as varchar(1))
                set @i = @i+1
            end
            update Member set MemberPwd = @pwd where MemberAccount=@acc
        end
    end
go
--调用
declare @pwd nvarchar(20) = '123456'
exec procPwdUpgrade 'liubei',@pwd output
select @pwd

为了支持输入输出参数,给DBHelper添加方法:

/// <summary>
/// 设置输入输出参数(不指定长度,适合非字符串)
/// </summary>
/// <param name="parameterName">参数名称</param>
/// <param name="dbType">参数类型</param>
public static void SetInOutParameter(string parameterName, SqlDbType dbType, object parameterValue)
{
    parameterName = "@" + parameterName.Trim();
    SqlParameter parameter = new SqlParameter(parameterName, dbType);
    parameter.Value = parameterValue;
    parameter.Direction = ParameterDirection.InputOutput;
    adp.SelectCommand.Parameters.Add(parameter);
}
/// <summary>
/// 设置输入输出参数(指定长度,适合字符串)
/// </summary>
/// <param name="parameterName">参数名称</param>
/// <param name="dbType">参数类型</param>
/// <param name="size">参数长度</param>
public static void SetInOutParameter(string parameterName, SqlDbType dbType, int size, object parameterValue)
{
    parameterName = "@" + parameterName.Trim();
    SqlParameter parameter = new SqlParameter(parameterName, dbType, size);
    parameter.Value = parameterValue;
    parameter.Direction = ParameterDirection.InputOutput;
    adp.SelectCommand.Parameters.Add(parameter);
}

窗体代码:

//密码升级,传入用户名和密码,
//如果用户名密码正确,并且密码长度<8,自动升级成8位密码
private void btUpgrade_Click(object sender, EventArgs e)
{
    DBHelper.PrepareProc("procPwdUpgrade");
    DBHelper.SetParameter("acc", this.txtAccount.Text);
    DBHelper.SetInOutParameter("pwd", SqlDbType.NVarChar, 20, this.txtPwd.Text);
    DBHelper.ExecNonQuery();
    this.lblNewPwd.Text = DBHelper.GetParameter("pwd").ToString();
}

(5)调用有返回值的存储过程

SQLSERVER存储过程返回值只能是整数。


0045.PNG

需求:实现数据的新增,由SQLSERVER返回执行的状态。

主要代码:

SQL存储过程代码:

--添加会员信息(有返回值)
create proc procInsertMember
    @acc nvarchar(20),
    @pwd nvarchar(20),
    @memName nvarchar(20),
    @memPhone nvarchar(20)
as
    insert into Member(MemberAccount,MemberPwd,MemberName,MemberPhone)
    values(@acc,@pwd,@memName,@memPhone)
    declare @myErr int = @@error
    if @myErr = 0
        return 1
    else if @myErr = 2627 --唯一约束
        return -1
    else
        return -100
go
--调用
declare @return int
exec @return = procInsertMember 'sunwukong','123456','孙悟空','13554854785'
print @return

为了支持返回值,给DBHelper添加方法:

/// <summary>
/// 设置返回值参数
/// </summary>
/// <param name="parameterName">参数名称</param>
public static void SetReturnParameter(string parameterName)
{
    parameterName = "@" + parameterName.Trim();
    SqlParameter parameter = new SqlParameter();
    parameter.ParameterName = parameterName;
    parameter.Direction = ParameterDirection.ReturnValue;
    adp.SelectCommand.Parameters.Add(parameter);
}

窗体代码:

private void btAdd_Click(object sender, EventArgs e)
{
    try
    {
        DBHelper.PrepareProc("procInsertMember");
        DBHelper.SetParameter("acc", this.txtAccount.Text);
        DBHelper.SetParameter("pwd", this.txtPwd.Text);
        DBHelper.SetParameter("memName", this.txtNickName.Text);
        DBHelper.SetParameter("memPhone", this.txtPhone.Text);
        DBHelper.SetReturnParameter("returnValue");
        DBHelper.ExecNonQuery();
        int result = (int)DBHelper.GetParameter("returnValue");
        if (result == 1)
            MessageBox.Show("添加成功!");
    }
    catch (Exception ex)
    {
        int result = (int)DBHelper.GetParameter("returnValue");
        if (result == -1)
            MessageBox.Show("用户名重名了,违反了唯一约束!");
        if (result == -100)
            MessageBox.Show(ex.Message);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容