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. 還有一些是必須遵守的一些默認規則,比如:
先過濾後連接。
查詢的欄位最要不要用「*」,指定需要用的欄位,減少網路流量。
『總結』
對於性能的追求是沒有極限的,做到你所能做到的,這是一個很好的習慣。
有些業務邏輯放在存儲過程中處理比較方便,而有些業務邏輯交給程序來處理,同樣會提升系統整體的效率,看實際情況而定。
總之,盡可能減少這些容易引發性能問題的隱患,系統就會跑得更穩定更有效率,一切從小細節做起。