㈠ sql游標怎麼循環更新
應該不是游標問題,是循環內的判定問題,@i一直沒變過,所以 @i>100不會命中。將set @i提出來:
WHILE @@FETCH_STATUS = 0
BEGIN
set @i = @i + 1
if(@i > 100)
begin
update #aa set @ewaibutie = 5
end
FETCH NEXT from cur_man into @ewaibutie
END
CLOSE cur_man
㈡ sqlserver 游標有哪些屬性
樓上你的,你說的是oracle的,不是sqlserver的
游標(Cursor)是處理數據的一種方法,為了查看或者處理結果集中的數據,游標提供了在結果集中一次以行或者多行前進或向後瀏覽數據的能力。我們可以把游標當作一個指針,它可以指定結果中的任何位置,然後允許用戶對指定位置的數據進行處理。
1.游標的組成
游標包含兩個部分:一個是游標結果集、一個是游標位置。
游標結果集:定義該游標得SELECT語句返回的行的集合。游標位置:指向這個結果集某一行的當前指針。
2.游標的分類
游標共有3類:API伺服器游標、Transaction-SQL游標和API客戶端游標。
其中前兩種游標都是運行在伺服器上的,所以又叫做伺服器游標。
API伺服器游標
API伺服器游標主要應用在服務上,當客戶端的應用程序調用API游標函數時,伺服器會對API函數進行處理。使用API函數和方法可以實現如下功能:
(1)打開一個連接。
(2)設置定義游標特徵的特性或屬性,API自動將游標影射到每個結果集。
(3)執行一個或多個Transaction-SQL語句。
(4)使用API函數或方法提取結果集中的行。
API伺服器游標包含以下四種:靜態游標、動態游標、只進游標、鍵集驅動游標(Primary key)
靜態游標的完整結果集將打開游標時建立的結果集存儲在臨時表中,(靜態游標始終是只讀的)。靜態游標具有以下特點:總是按照打開游標時的原樣顯示結果集;不反映資料庫中作的任何修改,也不反映對結果集行的列值所作的更改;不顯示打開游標後在資料庫中新插入的行;組成結果集的行被其他用戶更新,新的數據值不會顯示在靜態游標中;但是靜態游標會顯示打開游標以後從資料庫中刪除的行。
動態游標與靜態游標相反,當滾動游標時動態游標反映結果集中的所有更改。結果集中的行數據值、順序和成員每次提取時都會改變。
只進游標不支持滾動,它只支持游標從頭到尾順序提取數據行。注意:只進游標也反映對結果集所做的所有更改。
鍵集驅動游標同時具有靜態游標和動態游標的特點。當打開游標時,該游標中的成員以及行的順序是固定的,鍵集在游標打開時也會存儲到臨時工作表中,對非鍵集列的數據值的更改在用戶游標滾動的時候可以看見,在游標打開以後對資料庫中插入的行是不可見的,除非關閉重新打開游標。
Transaction-SQL游標
該游標是基於Declare Cursor 語法,主要用於Transaction-SQL腳本、存儲過程以及觸發器中。Transaction-SQL游標在伺服器處理由客戶端發送到伺服器的Transaction-SQL語句。
在存儲過程或觸發器中使用Transaction-SQL游標的過程為:
(1)聲明Transaction-SQL變數包含游標返回的數據。為每個結果集列聲明一個變數。聲明足夠大的變數來保存列返回的值,並聲明變數的類型為可從數據類型隱式轉換得到的數據類型。
(2)使用Declare Cursor語句將Transaction-SQL游標與Select語句相關聯。還可以利用Declare Cursor定義游標的只讀、只進等特性。
(3)使用Open語句執行Select語句填充游標。
(4)使用Fetch Into語句提取單個行,並將每列中得數據移至指定的變數中。注意:其他Transaction-SQL語句可以引用那些變數來訪問提取的數據值。Transaction-SQL游標不支持提取行塊。
(5)使用Close語句結束游標的使用。注意:關閉游標以後,該游標還是存在,可以使用Open命令打開繼續使用,只有調用Deallocate語句才會完全釋放。
客戶端游標
該游標將使用默認結果集把整個結果集高速緩存在客戶端上,所有的游標操作都在客戶端的高速緩存中進行。注意:客戶端游標只支持只進和靜態游標。不支持其他游標。
3.游標的生命周期
游標的生命周期包含有五個階段:聲明游標、打開游標、讀取游標數據、關閉游標、釋放游標。
聲明游標是為游標指定獲取數據時所使用的Select語句,聲明游標並不會檢索任何數據,它只是為游標指明了相應的Select 語句。
Declare 游標名稱 Cursor 參數
聲明游標的參數
(1)Local與Global:Local表示游標的作用於僅僅限於其所在的存儲過程、觸發器以及批處理中、執行完畢以後游標自動釋放。Global表示的是該游標作用域是整個會話層。由連接執行的任何存儲過程、批處理等都可以引用該游標名稱,僅在斷開連接時隱性釋放。
(2)Forward_only與Scroll:前者表示為只進游標,後者表示為可以隨意定位。默認為前者。
(3)Static、Keyset與Dynamic: 第一個表示定義一個游標,其數據存放到一個臨時表內,對游標的所有請求都從臨時表中應答,因此,對該游標進行提取操作時返回的數據不反映對基表所作的修改,並且該游標不允許修改。Keyset表示的是,當游標打開時,鍵集驅動游標中行的身份與順序是固定的,並把其放到臨時表中。Dynamic表示的是滾動游標時,動態游標反映對結果集內所有數據的更改。
(4)Read_only 、Scroll_Locks與Optimistic:第一個表示的是只讀游標,第二個表示的是在使用的游標結果集數據上放置鎖,當行讀取到游標中然後對它們進行修改時,資料庫將鎖定這些行,以保證數據的一致性。Optimistic的含義是游標將數據讀取以後,如果這些數據被更新了,則通過游標定位進行的更新與刪除操作將不會成功。
標准游標:
Declare MyCursor Cursor
For Select * From Master_Goods
只讀游標
Declare MyCusror Cursor
For Select * From Master_Goods
For Read Only
可更新游標
Declare MyCusror Cursor
For Select * From Master_Goods
For UpDate
打開游標使用Open語句用於打開Transaction-SQL伺服器游標,執行Open語句的過程中就是按照Select語句進行填充數據,打開游標以後游標位置在第一行。
打開游標
全局游標:Open Global MyCursor 局部游標: Open MyCursor
讀取游標數據:在打開游標以後,使用Fetch語句從Transaction-SQL伺服器游標中檢索特定的一行。使用Fetch操作,可以使游標移動到下一個記錄,並將游標返回的每個列得數據分別賦值給聲明的本地變數。
Fetch [Next | Prior | First | Last | Absoluten| Relativen] From MyCursor
Into @GoodsID,@GoodsName
其中:Next表示返回結果集中當前行的下一行記錄,如果第一次讀取則返回第一行。默認的讀取選項為Next
Prior表示返回結果集中當前行的前一行記錄,如果第一次讀取則沒有行返回,並且把游標置於第一行之前。
First表示返回結果集中的第一行,並且將其作為當前行。
Last表示返回結果集中的最後一行,並且將其作為當前行。
Absoluten如果n為正數,則返回從游標頭開始的第n行,並且返回行變成新的當前行。如果n為負,則返回從游標末尾開始的第n行,並且返回行為新的當前行,如果n為0,則返回當前行。
Relativen如果n為正數,則返回從當前行開始的第n行,如果n為負,則返回從當前行之前的第n行,如果為0,則返回當前行。
關閉游標調用的是Close語句,方式如下:Close Global MyCursor Close MyCursor
釋放游標調用的是Deallocate語句,方法如下:Deallocate Glboal MyCursor Deallocate MyCursor
游標實例:
Declare MyCusror Cursor Scroll
For Select * From Master_Goods Order By GoodsID
Open MyCursor
Fetch next From MyCursor
Into @GoodsCode,@GoodsName
While(@@Fetch_Status = 0)
Begin
Begin
Select @GoodsCode = Convert(Char(20),@GoodsCode)
Select @GoodsName = Convert(Char(20),@GoodsName)
PRINT @GoodsCode + ':' + @GoodsName
End
Fetch next From MyCursor
Into @GoodsCode,@GoodsName
End
Close MyCursor
Deallocate MyCursor
修改當前游標的數據方法如下:
UpDate Master_Goods Set GoodsName = 'yangyang8848' Where Current Of MyCursor;
刪除當前游標行數據的方法如下:
Delete From Master_Goods Where Current Of MyCursor
Select @@CURSOR_ROWS 可以得到當前游標中存在的數據行數。注意:此變數為一個連接上的全局變數,因此只對應最後一次打開的游標。
㈢ sqlserver中怎樣使用游標for循環
給你舉個例子
利用游標循環更新、刪除MemberAccount表中的數據
DECLARE My_Cursor CURSOR --定義游標
FOR (SELECT * FROM dbo.MemberAccount) --查出需要的集合放到游標中
OPEN My_Cursor; --打開游標
FETCH NEXT FROM My_Cursor ; --讀取第一行數據
WHILE @@FETCH_STATUS = 0
BEGIN
--UPDATE dbo.MemberAccount SET UserName = UserName + 'A' WHERE CURRENT OF My_Cursor; --更新
--DELETE FROM dbo.MemberAccount WHERE CURRENT OF My_Cursor; --刪除
FETCH NEXT FROM My_Cursor; --讀取下一行數據
END
CLOSE My_Cursor; --關閉游標
DEALLOCATE My_Cursor; --釋放游標
GO
㈣ 請問mssql中,用循環游標update列數據的方法
--建立環境
create table t1
(
id int
)
--插入數據,這里插入奇數
declare @i int
select @i = 0
while (@i < 100)
begin
insert into t1 select @i * 2 +1
select @i = @i + 1
end
--游標處理
declare @ii int
declare @k int
select @k = 1,@ii = 1
declare c_update_id cursor for
select id from t1
for update
open c_update_id
fetch next from c_update_id into @ii
while(@@fetch_status=0)
begin
update t1 set id = @k where current of c_update_id
fetch next from c_update_id into @ii
select @k = @k + 1
end
CLOSE c_update_id
DEALLOCATE c_update_id
--查詢
select * from t1
--刪除環境
drop table t1
--以上代碼在sql server 2005 測試通過
PS: 如果這個表有主鍵的話,就非常簡單,不用游標,一條update語句搞定。
㈤ SQL 循環更新
問題出在這里:
begin
UPDATE orders set qty = @i
set @i = @i + 1
你第八次更新後就把表orders的qty全部更新成8了,你要加條件,如:
begin
UPDATE orders set qty = @i
where id = @i
set @i = @i + 1
那就會按照id來更新,根據id 1到8 更新
㈥ SQLserver 大批量更新插入的時候游標怎麼優化
盡量避免使用游標,因為游標的效率較差,如果游標操作的數據超過1萬行,那麼就應該考慮改寫。
使用基於游標的方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。
最好的改進游標性能的技術就是:能避免時就避免使用游標
若有時無法避免使用游標,則可以用如下技巧來優化游標的性能。
(1). 除非必要否則不要使用static/insensitive游標。打開static游標會造成所有的行都被拷貝到臨時表。這正是為什麼它對變化不敏感的原因——它實際上是指向臨時資料庫表中的一個備份。很自然,結果集越大,聲明其上的static游標就會引起越多的臨時資料庫的資源爭奪問題。
(2). 除非必要否則不要使用keyset游標。和static游標一樣,打開keyset游標會創建臨時表。雖然這個表只包括基本表的一個關鍵字列(除非不存在唯一關鍵字),但是當處理大結果集時還是會相當大的。
(3). 當處理單向的只讀結果集時,使用fast_forward代替forward_only。使用fast_forward定義一個forward_only,則read_only游標具有一定的內部性能優化。
(4). 使用read_only關鍵字定義只讀游標。這樣可以防止意外的修改,並且讓伺服器了解游標移動時不會修改行。
(5). 小心事務處理中通過游標進行的大量行修改。根據事務隔離級別,這些行在事務完成或回滾前會保持鎖定,這可能造成伺服器上的資源爭奪。
(6). 小心動態游標的修改,尤其是建在非唯一聚集索引鍵的表上的游標,因為他們會造成「Halloween」問題——對同一行或同一行的重復的錯誤的修改。因為SQL Server在內部會把某行的關鍵字修改成一個已經存在的值,並強迫伺服器追加下標,使它以後可以再結果集中移動。當從結果集的剩餘項中存取時,又會遇到那一行,然後程序會重復,結果造成死循環。
(7). 對於大結果集要考慮使用非同步游標,盡可能地把控制權交給調用者。當返回相當大的結果集到可移動的表格時,非同步游標特別有用,因為它們允許應用程序幾乎馬上就可以顯示行
㈦ sqlserver中游標循環中只更新當前行的方法
如果您只是想要針對查詢到的資料進行一些簡單的新增、更新或刪除資料,您可以藉由ResultSet的一些方法來執行,而不一定要撰寫SQL並執行。
想要使用ResultSet直接進行新增、更新或刪除資料,在建立Statement時必須在createStatement()上指定 ResultSet.TYPE_SCROLL_SENSITIVE(或ResultSet.TYPE_SCROLL_INSENSITIVE,如果不想取得更新後的資料的話)與ResultSet.CONCUR_UPDATABLE,例如:
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
假如我們想要針對查詢到的資料進行更新的動作,我們先移動游標至想要更新的資料位置,然後使用updateXXX()等對應的方法即可,最後記得使用 updateRow()讓更新生效,例如:
ResultSet result = stmt.executeQuery(
"SELECT * FROM message WHERE name='caterpillar'");
result.last();
result.updateString("name", "justin");
result.updateString("email", "[email protected]");
result.updateRow();
使用updateXXX()等方法之後,並不會馬上對資料庫生效,而必須執行完updateRow()方法才會對資料庫進行操作,如果在 updateRow()前想要取消之前的updateXXX()方法,則可以使用cancelRowUpdates()方法取消。
如果想要新增資料,則先使用moveToInsertRow()移至新增資料處,執行相對的updateXXX()方法,然後再執行insertRow ()即可新增資料,例如:
ResultSet result = stmt.executeQuery(
"SELECT * FROM message WHERE name='caterpillar'");
result.moveInsertRow();
result.updateString("name", "caterpillar");
result.updateString("email", "[email protected]");
result.updateString("subject", "test");
result.updateString("memo", "This is a test!");
result.insertRow();
如果想要刪除查詢到的某筆資料,則可以將游標移至該筆資料,然後執行deleteRow()方法即可:
ResultSet result = stmt.executeQuery(
"SELECT * FROM message WHERE name='caterpillar'");
result.last();
result.deleteRow();
---------------------------------------------------------------
Statement stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATBALE);
ResultSet uprs=stmt.executeQuery("select username,sex from talbe_name");
uprs.last();
uprs.updateString(1,"aaa");
uprs.updateString(2,"男");
uprs.updateRow();
㈧ SqlServer 游標不能循環
語法邏輯上看沒什麼問題,建議在存儲過程中加入PRINT語句,再調用存儲過程看一直處理的過程是否有循環
WHILE @@FETCH_STATUS=0
BEGIN
print @ordno
㈨ 關於SQL Server的循環更新問題
建表[M_Info做表名日期[M_Datetime],總數[Fssums],已用[Used],剩餘[Brand_new]:
CREATETableM_Info(
M_DatetimeDatetime,
Fssumsint,
Usedint,
Brand_newint)
INSERTINTOM_InfoValues('2013-05-31',5,0,5)
INSERTINTOM_InfoValues('2013-06-30',10,0,10)
代碼部分:
DECLARE@Inputint
DECLARE@MinDTDateTime
SET@Input=6
While@Input>0
begin
SELECT@MinDT=MIN(M_Datetime)fromM_InfowhereBrand_new>0
UPDATEASETA.Used=A.Used+1,A.Brand_new=A.Brand_new-1FROMM_InfoA
WHEREA.Brand_new>0ANDA.M_Datetime=@MinDT
SET@Input=@Input-1
end
我覺得有更好的辦法, 使用同表連接用Exists來判斷日期, 我這里用了一個@MinDT變數, 我的意思是這個變數應該有辦法不使用的!期待高手!
㈩ sql 游標如何循環
SQL游標的優點是可以方便從一個結果集中進行循環遍歷數據在進行操作,下面就將為您介紹用SQL游標對數據進行遍歷循環操作的方法,供您參考。
AD:
如果對數據進行遍歷循環操作,通過SQL的游標就可以實現,下面就為您詳細介紹該方法,供您參考,希望對您學習SQL資料庫能夠有所幫助。
SQL游標的優點是可以方便從一個結果集中進行循環遍歷數據在進行操作。
1、游標允許應用程序對查詢語句select 返回的行結果集中每一行進行相同或不同的操作,而不是一次對整個結果集進行同一種操作;
2、它還提供對基於游標位置而對表中數據進行刪除或更新的能力;
3、游標把作為面向集合的資料庫管理系統和面向行的程序設計兩者聯系起來,使兩個數據處理方式能夠進行溝通。
然爾游標也有缺點——復雜和低效,是游標的最大缺點,也是致使很多時候在使用存儲過程中沒有想到游標的主要原因。
下面是在實際工作中的一個游標實例的應用,通過游標把A表的數據的一列值復制到B表的列當中,其中二個表都有相同的UID欄位,條件是對相同UID的數據進行復制.
declare @level varchar(100)
declare @uid varchar(100)
declare cur cursor--定義一個游標
read_only
for select egg_code.user_id,egg_prize_level
from egg_code inner join egg_prize on egg_prize.user_id=egg_code.user_id--為所獲得的數據集指定游標
open cur--打開游標
fetch next from cur into @uid,@level--把提取操作的列數據放到局部變數中
while(@@fetch_status=0)--返回被 FETCH 語句執行的最後游標的狀態,而不是任何當前被連接打開的游標的狀態。
begin
--print '等級:'+@level+'--------------用戶ID:'+@uid
update egg_code set prize_level=@level where user_id=@uid--執行操作
--提前下一位信息
fetch next from cur into @uid,@level
end
close cur--關閉游標
deallocate cur--刪除游標
go
使用游標的順序: 聲名游標、打開游標、讀取數據、關閉游標、刪除游標。
由於 @@FETCH_STATUS 對於在一個連接上的所有游標是全局性的,要小心使用 @@FETCH_STATUS 。在執行一條 FETCH 語句後,必須在對另一游標執行另一 FETCH 語句前測試 @@FETCH_STATUS 。在任何提取操作出現在此連接上前,@@FETCH_STATUS 的值沒有定義。
例如,用戶從一個游標執行一條 FETCH 語句,然後調用一個存儲過程,此存儲過程打開並處理另一個游標的結果。當控制從被調用的存儲過程返回後,@@FETCH_STATUS 反映的是在存儲過程中執行的最後的 FETCH 語句的結果,而不是在存儲過程被調用之前的 FETCH 語句的結果。
使用上面的游標是泉州SEO在一次網站砸金蛋活動中,二個表的數據在使用的過程中有部份後期改到程序致使有部份數據無法同步,導致前台查詢的時候所用到的表無法查到相關的數據,沒用游標進行操作之前試過只用簡單的SQL語句去實現這樣的同步功能,但是始終無法實現,所以只能使用游標來實現。