sql存储过程trycatch
㈠ 对象不能从 DBNull 转换为其他类型。
prmSid.Value 返回的值是 DBNull,也就是说相当于数据库单元格中什么值也没有。
你需要事先判断这种情况。
㈡ 如何把sql语句查询到的值赋值给变量
//多行
System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection("server=.;database=你的数据库的名字;uid=sa;pwd=sa的密码;");
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
cmd.Connection = conn;
cmd.CommandText="select 字段A from 表B where years=2000 and months=2";
conn.Open();
System.Data.SqlDataAdapter sda=new System.Data.SqlDataAdapter(cmd);
DataSet ds=new DataSet();
sda.Fill(ds,"dtResult");
conn.Close();
//结果在ds的dtResult中。
foreach(DataRow dr in ds.Tables["dtResult"])
{
Response.Write(dr["字段A"].ToString()+"<br>");
}
-------------------------------------------------------------
System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection("server=.;database=你的数据库的名字;uid=sa;pwd=sa的密码;");
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
cmd.Connection = conn;
cmd.CommandText="select 字段A from 表B where years=2000 and months=2";
conn.Open();
int i=Convert.ToInt32(cmd.ExecuteScalar().ToString());
conn.Close();
㈢ mysql存储过程中有没有类似try catch
在存储过程中使用事务时,如果没有try…catch语句,那么当set xact_abort
on时,如果有错误发生,在批处理语句结束后,系统会自动回滚所有的sql操作。当set xact_abort
off时,如果有错误发生,在批处理语句结束后,系统会执行所有没有发生错误的语句,发生错误的语句将不会被执行。
在存储过程中使用事务时,如果存在try…catch语句块,那么当捕获到错误时,需要在catch语句块中手动进行Rollback操作,否则系统会给客户端传递一条错误信息。如果在存储过程开始处将set
xact_abort
on,那么当有错误发生时,系统会将当前事务置为不可提交状态,即会将xact_state()置为-1,此时只可以对事务进行Rollback操作,不可进行提交(commit)操作,那么我们在catch语句块中就可以根据xact_state()的值来判断是否有事务处于不可提交状态,如果有则可以进行rollback操作了。如果在存储过程开始处将set
xact_abort
off,那么当有错误发生时,系统不会讲xact_state()置为-1,那么我们在catch块中就不可以根据该函数值来判断是否需要进行
rollback了,但是我们可以根据@@Trancount全局变量来判断,如果在catch块中判断出@@Trancount数值大于0,代表还有未提交的事务,既然进入catch语句块了,那么还存在未提交的事务,该事务应该是需要rollback的,但是这种方法在某些情况下可能判断的不准确。推荐的方法还是将set
xact_abort on,然后在catch中判断xact_state()的值来判断是否需要Rollback操作。
下面我们来看看两个例子:
一.使用Set xact_abort on
代码
Create proc myProcere
As
begin
set xact_abort on;
begin try
begin tran
insert into TestStu values('Terry','boy',23);
insert into TestStu values('Mary','girl',21);
commit tran
end try
begin catch
--在此可以使用xact_state()来判断是否有不可提交的事务,不可提交的事务
--表示在事务内部发生错误了。Xact_state()有三种值:-1.事务不可提交;
--1.事务可提交;0.表示没有事务,此时commit或者rollback会报错。
if xact_state()=-1
rollback tran;
end catch
end
二.使用Set xact_abort off
代码
Create proc myProcere
As
begin
set xact_abort off;
begin try
begin tran
insert into TestStu values('Terry','boy',23);
insert into TestStu values('Mary','girl',21);
commit tran
end try
begin catch
--在此不可以使用xact_state来判断是否有不可提交的事务
--只可以使用@@Trancount来判断是否有还未提交的事务,未提交的事务未必
--就是不可提交的事务,所以使用@@TranCount>0后就RollBack是不准确的
if @@TranCount>0
rollback tran;
end catch
end
另外,对于@@Trancount需要说明的是,begin tran 语句将 @@Trancount加 1。Rollback tran将
@@Trancount递减到 0,但 Rollback tran savepoint_name 除外,它不影响 @@Trancount。Commit tran 或 Commit work 将 @@Trancount 递减 1。
㈣ Sqlserver 8.0.2039 存储过程怎样写try catch
sql2005 以下版本没有 try catch语句块;
通常采用 @@error 来判断;
code:
declare @error int
set @error = 0
begin tran
--your sql here and exceut
set @error = @@error + @error
if(@error <> 0 ) --has error
begin
rollback ;
return;
end
--another sql code and excut it ..
set @error = @@error + @error
if(@error <> 0 ) --has error
begin
rollback ;
return;
end
commit
㈤ C#创建代码创建SQL数据库
建议你把所有的对数据库的操作都写在sql
server数据库存储过程中,然后通过C#代码
执行这些个存储过程,完成功能,这样做执行速度快,安全性高,这是最佳方案。
如果你非要用C#代码来做这些操作,就把这些sql语句写在业务逻辑层中(若是winForm写在客户端后台代码里,若是webForm项目就写在页面后台代码里),然后执行sql语句,完成功能。
以下是C#连接数据库的代码:
public
static
SqlConnection
CreateSqlConnection()
{
SqlConnection
conn
=
new
SqlConnection("server=.;database=marsDB;uid=sa;pwd=;");
return
conn;
}
public
class
DBoperate
{
SqlConnection
con;
SqlCommand
cmd;
public
DBoperate()
{
try{
con
=
marsDB.CreateSqlConnection();
con.Open();
cmd
=
new
SqlCommand();
cmd.Connection
=
con;
}catch
{
}
}
public
void
DBConRelease()
{
try
{
con.Close();
}
catch
{
}
}
public
DataSet
CreateDs(string
sqlCmdText,string
dtName)
{
cmd.CommandText
=
sqlCmdText;
SqlDataAdapter
sda
=
new
SqlDataAdapter(cmd);
DataSet
ds
=
new
DataSet();
sda.Fill(ds,
dtName);
return
ds;
}
public
bool
UserQuery(string
userAccount)
{
cmd.CommandText
=
"select
count(*)
from
TB_userInfo
where
userAccount
='"+userAccount+"'";
int
count
=
Convert.ToInt32(cmd.ExecuteScalar());
if
(count
>
0)
{
return
true;
}
else
{
return
false;
}
}
public
bool
AdminQuery(string
adminAccount)
{
cmd.CommandText
=
"select
count(*)
from
TB_admin
where
adminAccount
='"
+
adminAccount
+
"'";
int
count
=
Convert.ToInt32(cmd.ExecuteScalar());
if
(count
>
0)
{
return
true;
}
else
{
return
false;
}
}
㈥ 请教在C#中如何调用SQL数据库计划任务中存储过程的执行
调用带返回值的存储过程:
--SQLServer运行面下语句生成测试用存储过程:
CreateProcgt_Address
@p_psnNameNvarChar(5)//请输入姓名
@g_psnAddressNvarChar(5)OutPut//返回此人的地址
As
Select@g_psnAddress=psnAddressFromPerson
WherepsnName=@p_psnName
If@@Error<>0
Return-1//如果查询语句出错返回-1
Else
Return0
Go
//C#中调用这个存储过程的部分代码如下:
SqlConnectioncn=newSqlConnection("server=.;database=test;uid=sa;pwd=123456");
try
{
cn.Open();
SqlCommandcmd=newSqlCommand("gt_Address",cn);
cmd.CommandType=CommandType.StoredProcere;
//加入参数,并设置参数的值和Direction属性
cmd.Parameters.Add("@p_psnName",SqlDbType.NvarChar).Value="帕瓦罗蒂";
SqlParametercpar=cmd.Parameters.Add("@g_psnAddress",SqlDbType.NvarChar,50);
cpar.Direction=ParameterDirection.Output;
SqlParametercres=cmd.Parameters.Add("@return",SqlDbType.Int);
cres.Direction=ParameterDirection.ReturnValue;
//执行存储过程
cmd.ExecuteNonQuery();
//获得参数的值
intres=(int)cres.Value;
stringaddress=(string)cpar.Value;
Console.WriteLine("返回值:{0},地址:{1}",res,address);
}
catch(SqlExceptionex)
{
//数据库出错信息报告
}
finally
{
cn.Close();
}
㈦ SQL 创建存储过程 输出对比参数
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
create PROCEDURE [dbo].[proc_return]
@货物编号 nvarchar(50),--不清楚你的这个货物编号是要传进来还是要 在存储过程获取
@ReturnCount Int OutPut
AS
Begin
Begin TransacTion trans
Set @ReturnCount = 3 --这里先默认为3或者其他 ,如果要检测其他错误的话 会要用到 食物
--执行取得 货物编号 语句或者 存储过程
if(@货物编号='') --这里可以看成判断没有给出 货物编号
begin
select @ReturnCount=1
end
If Exists(Select * From 货物表 Where 货物编号 = @货物编号)--判断是否存在
Begin
select @ReturnCount=0
End
Else
Begin
select @ReturnCount=2
End
if @@error<>0 --判断如果以上执行有任何一条出现错误
begin
rollback tran --开始执行事务的回滚,恢复的转账开始之前状态
select @ReturnCount=3
end
else
begin
commit tran
end
End
呵呵 希望对你有所帮助。
㈧ 如何在JDBC里调用PLSQL创建的存储过程
import oracle.jdbc.*;
import oracle.sql.*;
import java.sql.*;
public class ReturnIndexTable
{
Connection ociconn=null;
OracleCallableStatement stmt =null;
public String[] getTable(String in_param)
{
String[] reAry=null;
try
{
OracleDriver S_Driver=null;
if(S_Driver==null)
S_Driver=new oracle.jdbc.OracleDriver();
DriverManager.registerDriver(S_Driver);
String url="jdbc:oracle:oci8:@test";
String user="user";
String password=" password";
ociconn= DriverManager.getConnection(url,user,password);
stmt =(OracleCallableStatement)ociconn.prepareCall("begin yejf_count(?,?); end;");
// 返回的索引表最大长度(可以大于索引表实际长度)
int maxLen =31;
// 索引表元素类型
int elemSqlType = OracleTypes.VARCHAR;
//索引表元素长度(CHAR, VARCHAR or RAW),其它元素类型可忽略该项值,但该参数仍须定义
int elemMaxLen=50;
stmt.setString(1,in_param);
// 注册返回参数
stmt.(2,maxLen,elemSqlType,elemMaxLen);
stmt.execute();
// 返回数组类型
reAry=(String[])stmt.getPlsqlIndexTable(2);
}
catch (Exception e)
{e.printStackTrace();
}
finally
{return reAry;
}
}
//关闭连接.............
}
㈨ SQL Server 优化存储过程的方法有哪些
优化存储过程有很多种方法,下面介绍最常用的7种。
1.使用SET NOCOUNT ON选项
我们使用SELECT语句时,除了返回对应的结果集外,还会返回相应的影响行数。使用SET NOCOUNT ON后,除了数据集就不会返回额外的信息了,减小网络流量。
2.使用确定的Schema
在使用表,存储过程,函数等等时,最好加上确定的Schema。这样可以使SQL Server直接找到对应目标,避免去计划缓存中搜索。而且搜索会导致编译锁定,最终影响性能。比如select * from dbo.TestTable比select * from TestTable要好。from TestTable会在当前Schema下搜索,如果没有,再去dbo下面搜索,影响性能。而且如果你的表是csdn.TestTable的话,那么select * from TestTable会直接报找不到表的错误。所以写上具体的Schema也是一个好习惯。
3.自定义存储过程不要以sp_开头
因为以sp_开头的存储过程默认为系统存储过程,所以首先会去master库中找,然后在当前数据库找。建议使用USP_或者其他标识开头。
4.使用sp_executesql替代exec
原因在Inside Microsoft SQL Server 2005 T-SQL Programming书中的第四章Dynamic SQL里面有具体描述。这里只是简单说明一下:sp_executesql可以使用参数化,从而可以重用执行计划。exec就是纯拼SQL语句。
5.少使用游标
可以参考Inside Microsoft SQL Server 2005 T-SQL Programming书中的第三章Cursors里面有具体描述。总体来说,SQL是个集合语言,对于集合运算具有较高的性能,而Cursors是过程运算。比如对一个100万行的数据进行查询,游标需要读表100万次,而不使用游标只需要少量几次读取。
6.事务越短越好
SQL Server支持并发操作。如果事务过多过长,或是隔离级别过高,都会造成并发操作的阻塞,死锁。此时现象是查询极慢,同时cup占用率极低。
7.使用try-catch来处理错误异常
SQL Server 2005及以上版本提供对try-catch的支持,语法为:
begin try
----your code
end try
begin catch
--error dispose
end catch
一般情况可以将try-catch同事务结合在一起使用。
begin try
begin tran
--select
--update
--delete
--…………
commit
end try
begin catch
--if error
rollback
end catch
====================== 分割线 =======================
‘自己的一些调优经验’
1. 少使用游标是个很好的建议,为此,我自己也遇到过一些事故,是游标所造成的,由于,游标是逐行逐行操作的,当记录较多时,经常会遇到超时的情况。
2. 多表join做查询时,查询的字段尽量不要使用case when then else end的语法,或者使用用户函数,例如:
select (case when fType=1 then '是' else '否' end) as fTypeName, dbo.F_GetFullName(fID) as fFullName from Table1 inner join Table2……
当两个表的数据量非常大时,你可以在查询分析器中明显感觉到:直接查询fType和fID与查询上面两个字段的速度,很可能使用了一个case when then就导致超时。
针对这种情况,可以分两种做法:
第一,把一些简单的转换可以放在程序中完成。
第二,如果需要通过ID查询全名或者全称,类似的,可以创建好视图,直接查视图,或者,先把所有的fFullName查出来放到临时表中,直接join临时表(如果这个数据不是很多的话),获得fFullName。
3. 少使用一些嵌套的查询,用临时表缓存中间数据,例如:
select * from Table1
inner join (
select count(1) as count, Table2.ID2 from Table2 inner join Table3 on ID2=ID3 group by Table2.ID2
) as t1 on t1.ID1 = Table1.ID1
我曾经遇到这样情况,上面的语句是那种情况的简化版本,把其他不影响结果的表格都去掉了,发现一个奇怪的现象:嵌套查询的结果集并不大,大约就200多行,Table1有6w条记录,结果,这个查询语句超时,查询分析器中执行2分钟也得不到结果。
后来,这样一改,就Ok了,3秒出结果:
select count(1) as count, Table2.ID2 into #temp from Table2 inner join Table3 on ID2=ID3 group by Table2.ID2
select * from Table1
inner join #temp as t1 on t1.ID1 = Table1.ID1
这样一改,效率提升了几十倍,猜想:可能是嵌套的查询是动态的,每一行的join可能都需要先执行嵌套的查询,从而导致效率极差。
所以,如果查询足够复杂,join多个表,需要连接多个通过group by求和、求平均数等运算计算出来的中间数据,那么,不妨多使用临时表缓存中间数据。
4. 还有一些是必须遵守的一些默认规则,比如:
先过滤后连接。
查询的字段最要不要用“*”,指定需要用的字段,减少网络流量。
‘总结’
对于性能的追求是没有极限的,做到你所能做到的,这是一个很好的习惯。
有些业务逻辑放在存储过程中处理比较方便,而有些业务逻辑交给程序来处理,同样会提升系统整体的效率,看实际情况而定。
总之,尽可能减少这些容易引发性能问题的隐患,系统就会跑得更稳定更有效率,一切从小细节做起。