基本設(shè)計思路:
遷安ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書合作)期待與您的合作!
類型轉(zhuǎn)換、類型斷言、動態(tài)派發(fā)。iface,eface。
反射對象具有的方法:
編譯優(yōu)化:
內(nèi)部實現(xiàn):
實現(xiàn) Context 接口有以下幾個類型(空實現(xiàn)就忽略了):
互斥鎖的控制邏輯:
設(shè)計思路:
(以上為寫被讀阻塞,下面是讀被寫阻塞)
總結(jié),讀寫鎖的設(shè)計還是非常巧妙的:
設(shè)計思路:
WaitGroup 有三個暴露的函數(shù):
部件:
設(shè)計思路:
結(jié)構(gòu):
Once 只暴露了一個方法:
實現(xiàn):
三個關(guān)鍵點:
細節(jié):
讓多協(xié)程任務(wù)的開始執(zhí)行時間可控(按順序或歸一)。(Context 是控制結(jié)束時間)
設(shè)計思路: 通過一個鎖和內(nèi)置的 notifyList 隊列實現(xiàn),Wait() 會生成票據(jù),并將等待協(xié)程信息加入鏈表中,等待控制協(xié)程中發(fā)送信號通知一個(Signal())或所有(Boardcast())等待者(內(nèi)部實現(xiàn)是通過票據(jù)通知的)來控制協(xié)程解除阻塞。
暴露四個函數(shù):
實現(xiàn)細節(jié):
部件:
包: golang.org/x/sync/errgroup
作用:開啟 func() error 函數(shù)簽名的協(xié)程,在同 Group 下協(xié)程并發(fā)執(zhí)行過程并收集首次 err 錯誤。通過 Context 的傳入,還可以控制在首次 err 出現(xiàn)時就終止組內(nèi)各協(xié)程。
設(shè)計思路:
結(jié)構(gòu):
暴露的方法:
實現(xiàn)細節(jié):
注意問題:
包: "golang.org/x/sync/semaphore"
作用:排隊借資源(如錢,有借有還)的一種場景。此包相當(dāng)于對底層信號量的一種暴露。
設(shè)計思路:有一定數(shù)量的資源 Weight,每一個 waiter 攜帶一個 channel 和要借的數(shù)量 n。通過隊列排隊執(zhí)行借貸。
結(jié)構(gòu):
暴露方法:
細節(jié):
部件:
細節(jié):
包: "golang.org/x/sync/singleflight"
作用:防擊穿。瞬時的相同請求只調(diào)用一次,response 被所有相同請求共享。
設(shè)計思路:按請求的 key 分組(一個 *call 是一個組,用 map 映射存儲組),每個組只進行一次訪問,組內(nèi)每個協(xié)程會獲得對應(yīng)結(jié)果的一個拷貝。
結(jié)構(gòu):
邏輯:
細節(jié):
部件:
如有錯誤,請批評指正。
Goroutine調(diào)度是一個很復(fù)雜的機制,下面嘗試用簡單的語言描述一下Goroutine調(diào)度機制,想要對其有更深入的了解可以去研讀一下源碼。
首先介紹一下GMP什么意思:
G ----------- goroutine: 即Go協(xié)程,每個go關(guān)鍵字都會創(chuàng)建一個協(xié)程。
M ---------- thread內(nèi)核級線程,所有的G都要放在M上才能運行。
P ----------- processor處理器,調(diào)度G到M上,其維護了一個隊列,存儲了所有需要它來調(diào)度的G。
Goroutine 調(diào)度器P和 OS 調(diào)度器是通過 M 結(jié)合起來的,每個 M 都代表了 1 個內(nèi)核線程,OS 調(diào)度器負責(zé)把內(nèi)核線程分配到 CPU 的核上執(zhí)行
模型圖:
避免頻繁的創(chuàng)建、銷毀線程,而是對線程的復(fù)用。
1)work stealing機制
當(dāng)本線程無可運行的G時,嘗試從其他線程綁定的P偷取G,而不是銷毀線程。
2)hand off機制
當(dāng)本線程M0因為G0進行系統(tǒng)調(diào)用阻塞時,線程釋放綁定的P,把P轉(zhuǎn)移給其他空閑的線程執(zhí)行。進而某個空閑的M1獲取P,繼續(xù)執(zhí)行P隊列中剩下的G。而M0由于陷入系統(tǒng)調(diào)用而進被阻塞,M1接替M0的工作,只要P不空閑,就可以保證充分利用CPU。M1的來源有可能是M的緩存池,也可能是新建的。當(dāng)G0系統(tǒng)調(diào)用結(jié)束后,根據(jù)M0是否能獲取到P,將會將G0做不同的處理:
如果有空閑的P,則獲取一個P,繼續(xù)執(zhí)行G0。
如果沒有空閑的P,則將G0放入全局隊列,等待被其他的P調(diào)度。然后M0將進入緩存池睡眠。
如下圖
GOMAXPROCS設(shè)置P的數(shù)量,最多有GOMAXPROCS個線程分布在多個CPU上同時運行
在Go中一個goroutine最多占用CPU 10ms,防止其他goroutine被餓死。
具體可以去看另一篇文章
【Golang詳解】go語言調(diào)度機制 搶占式調(diào)度
當(dāng)創(chuàng)建一個新的G之后優(yōu)先加入本地隊列,如果本地隊列滿了,會將本地隊列的G移動到全局隊列里面,當(dāng)M執(zhí)行work stealing從其他P偷不到G時,它可以從全局G隊列獲取G。
協(xié)程經(jīng)歷過程
我們創(chuàng)建一個協(xié)程 go func()經(jīng)歷過程如下圖:
說明:
這里有兩個存儲G的隊列,一個是局部調(diào)度器P的本地隊列、一個是全局G隊列。新創(chuàng)建的G會先保存在P的本地隊列中,如果P的本地隊列已經(jīng)滿了就會保存在全局的隊列中;處理器本地隊列是一個使用數(shù)組構(gòu)成的環(huán)形鏈表,它最多可以存儲 256 個待執(zhí)行任務(wù)。
G只能運行在M中,一個M必須持有一個P,M與P是1:1的關(guān)系。M會從P的本地隊列彈出一個可執(zhí)行狀態(tài)的G來執(zhí)行,如果P的本地隊列為空,就會想其他的MP組合偷取一個可執(zhí)行的G來執(zhí)行;
一個M調(diào)度G執(zhí)行的過程是一個循環(huán)機制;會一直從本地隊列或全局隊列中獲取G
上面說到P的個數(shù)默認等于CPU核數(shù),每個M必須持有一個P才可以執(zhí)行G,一般情況下M的個數(shù)會略大于P的個數(shù),這多出來的M將會在G產(chǎn)生系統(tǒng)調(diào)用時發(fā)揮作用。類似線程池,Go也提供一個M的池子,需要時從池子中獲取,用完放回池子,不夠用時就再創(chuàng)建一個。
work-stealing調(diào)度算法:當(dāng)M執(zhí)行完了當(dāng)前P的本地隊列隊列里的所有G后,P也不會就這么在那躺尸啥都不干,它會先嘗試從全局隊列隊列尋找G來執(zhí)行,如果全局隊列為空,它會隨機挑選另外一個P,從它的隊列里中拿走一半的G到自己的隊列中執(zhí)行。
如果一切正常,調(diào)度器會以上述的那種方式順暢地運行,但這個世界沒這么美好,總有意外發(fā)生,以下分析goroutine在兩種例外情況下的行為。
Go runtime會在下面的goroutine被阻塞的情況下運行另外一個goroutine:
用戶態(tài)阻塞/喚醒
當(dāng)goroutine因為channel操作或者network I/O而阻塞時(實際上golang已經(jīng)用netpoller實現(xiàn)了goroutine網(wǎng)絡(luò)I/O阻塞不會導(dǎo)致M被阻塞,僅阻塞G,這里僅僅是舉個栗子),對應(yīng)的G會被放置到某個wait隊列(如channel的waitq),該G的狀態(tài)由_Gruning變?yōu)開Gwaitting,而M會跳過該G嘗試獲取并執(zhí)行下一個G,如果此時沒有可運行的G供M運行,那么M將解綁P,并進入sleep狀態(tài);當(dāng)阻塞的G被另一端的G2喚醒時(比如channel的可讀/寫通知),G被標(biāo)記為,嘗試加入G2所在P的runnext(runnext是線程下一個需要執(zhí)行的 Goroutine。), 然后再是P的本地隊列和全局隊列。
系統(tǒng)調(diào)用阻塞
當(dāng)M執(zhí)行某一個G時候如果發(fā)生了阻塞操作,M會阻塞,如果當(dāng)前有一些G在執(zhí)行,調(diào)度器會把這個線程M從P中摘除,然后再創(chuàng)建一個新的操作系統(tǒng)的線程(如果有空閑的線程可用就復(fù)用空閑線程)來服務(wù)于這個P。當(dāng)M系統(tǒng)調(diào)用結(jié)束時候,這個G會嘗試獲取一個空閑的P執(zhí)行,并放入到這個P的本地隊列。如果獲取不到P,那么這個線程M變成休眠狀態(tài), 加入到空閑線程中,然后這個G會被放入全局隊列中。
隊列輪轉(zhuǎn)
可見每個P維護著一個包含G的隊列,不考慮G進入系統(tǒng)調(diào)用或IO操作的情況下,P周期性的將G調(diào)度到M中執(zhí)行,執(zhí)行一小段時間,將上下文保存下來,然后將G放到隊列尾部,然后從隊列中重新取出一個G進行調(diào)度。
除了每個P維護的G隊列以外,還有一個全局的隊列,每個P會周期性地查看全局隊列中是否有G待運行并將其調(diào)度到M中執(zhí)行,全局隊列中G的來源,主要有從系統(tǒng)調(diào)用中恢復(fù)的G。之所以P會周期性地查看全局隊列,也是為了防止全局隊列中的G被餓死。
除了每個P維護的G隊列以外,還有一個全局的隊列,每個P會周期性地查看全局隊列中是否有G待運行并將其調(diào)度到M中執(zhí)行,全局隊列中G的來源,主要有從系統(tǒng)調(diào)用中恢復(fù)的G。之所以P會周期性地查看全局隊列,也是為了防止全局隊列中的G被餓死。
M0
M0是啟動程序后的編號為0的主線程,這個M對應(yīng)的實例會在全局變量rutime.m0中,不需要在heap上分配,M0負責(zé)執(zhí)行初始化操作和啟動第一個G,在之后M0就和其他的M一樣了
G0
G0是每次啟動一個M都會第一個創(chuàng)建的goroutine,G0僅用于負責(zé)調(diào)度G,G0不指向任何可執(zhí)行的函數(shù),每個M都會有一個自己的G0,在調(diào)度或系統(tǒng)調(diào)用時會使用G0的??臻g,全局變量的G0是M0的G0
一個G由于調(diào)度被中斷,此后如何恢復(fù)?
中斷的時候?qū)⒓拇嫫骼锏臈P畔?,保存到自己的G對象里面。當(dāng)再次輪到自己執(zhí)行時,將自己保存的棧信息復(fù)制到寄存器里面,這樣就接著上次之后運行了。
我這里只是根據(jù)自己的理解進行了簡單的介紹,想要詳細了解有關(guān)GMP的底層原理可以去看Go調(diào)度器 G-P-M 模型的設(shè)計者的文檔或直接看源碼
參考: ()
()
作為一個測試,作為一個測試開發(fā), 全?;?管理 是我們未來的發(fā)展方向。已經(jīng)掌握了Java、Python、HTML的你,是不是也想了解下最近異?;鸨腉o語言呢?來吧,讓我們一起了解下。
Go 是一個開源的編程語言 ,它能讓構(gòu)造簡單、可靠且高效的軟件變得容易。
Go是從2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持開發(fā),后來還加入了Ian Lance Taylor, Russ Cox等人,并最終于2009年11月開源,在2012年早些時候發(fā)布了Go 1穩(wěn)定版本?,F(xiàn)在Go的開發(fā)已經(jīng)是完全開放的,并且擁有一個活躍的社區(qū)。這三個人都是計算機界的大神,有的參與了C語言的編寫,有的還是數(shù)學(xué)大神,有的還獲得了計算機最高榮譽-圖靈獎。
接下來說說 Go語言的特色 :
簡潔、快速、安全
并行、有趣、開源
內(nèi)存管理、數(shù)組安全、編譯迅速
Go語言的用途 :
Go 語言被設(shè)計成一門應(yīng)用于搭載 Web 服務(wù)器,存儲集群或類似用途的巨型中央服務(wù)器的系統(tǒng)編程語言。
對于高性能分布式系統(tǒng)領(lǐng)域而言,Go 語言無疑比大多數(shù)其它語言有著更高的開發(fā)效率。它提供了海量并行的支持,這對于 游戲 服務(wù)端的開發(fā)而言是再好不過了。
Go語言的環(huán)境安裝:
建議直接打開 官方地址因為墻的原因打不開
因為我用的是windows系統(tǒng),這里主要講下Windows系統(tǒng)上使用Go語言來編程。
Windows 下可以使用 .msi 后綴(在下載列表中可以找到該文件,如go1.17.2.windows-amd64.msi)的安裝包來安裝。
默認情況下 .msi 文件會安裝在 c:Go 目錄下。你可以將 c:Gobin 目錄添加到 Path 環(huán)境變量中。添加后你需要重啟命令窗口才能生效。個人建議還是安裝到 Program Files文件夾中。
使用什么開發(fā)工具來對Go語言進行編寫:
個人建議用VS code, 也可以用Sublime Text來編輯。如果你之前看了我講的HTML語言的學(xué)習(xí),肯定已經(jīng)下載了VS code. 那么這時你需要在VS code中下載Go語言的擴展插件。
這里有一個巨大的坑,就是在下載Go的插件和依賴包時,會提示一些包沒有。主要是因為下載的依賴包部分被墻了,只能想別的辦法去下載。
建議參考網(wǎng)頁:
解決vscode中g(shù)olang插件安裝失敗方法
在學(xué)習(xí)go的過程中,使用的是vscode,但是一直提示安裝相關(guān)插件失敗,然后上網(wǎng)查方法,基本上是叫你建立golang.org目錄什么的,結(jié)果全是錯的,而且都是抄襲,很煩。無意之中看到一位博主分享的方法,他也是飽受上述的垃圾博文困擾,然后找到了解決方法,這里向他致敬,秉著讓更多人看到正確解決方法的心,我寫下正確的解決方法,希望對你有所幫助,也可以點開原博主鏈接參考:
Go有一個全球模塊代理,設(shè)置代理再去安裝golang的插件,就可以安裝成功了。步驟有,首先Windows用戶打開Powershell,一個藍色的界面,注意不是cmd!不知道的直接打開window下面的搜索,然后輸入powershell,搜索出來就可以了。
$env:GO111MODULE=“on”
$env:GOPROXY=“”
go env -w GOPROXY=
go env -w GOPRIVATE=*.corp.example.com
然后我們打開VsCode界面,下面會提示安裝插件,我們選擇Install ALL,就會安裝成功
當(dāng)你在運行Go語言程序時,提示所有的插件包都已經(jīng)安裝成功了時,就可以正常使用了,要不然一堆報錯會讓你非常心煩。
好了,今天先到這里,晚安、下班~
存儲過程
存儲過程是保存在數(shù)據(jù)庫中的專門進行數(shù)據(jù)操作的代碼過程。存儲過程通常與觸發(fā)器結(jié)合使用,來控制數(shù)據(jù)的完整性。在打開數(shù)據(jù)庫時,存儲過程被自動加載到內(nèi)存中,可以象其他過程文件一樣進行調(diào)用。
1.建立存儲過程
可以在項目管理器中選擇建立或修改存儲過程。在項目管理器的Data選項卡中選定Stored Procedures節(jié)點,然后單擊New、Add或Modify按鈕都將打開存儲過程文本編輯器,如圖7-12所示。
也可以在首先打開數(shù)據(jù)庫的情況下,執(zhí)行MODIFY STRUCTURE命令打開存儲過程文本編輯器。如:
OPEN DATABASE dbMyData
MODIFY STRUCTURE
一個數(shù)據(jù)庫的所有存儲過程包含在一個文件中,過程使用PROCEDURE語句聲明,這與一般的過程文件是完全一樣的。
例如,下面為數(shù)據(jù)庫建立了一個名為NewStuId的存儲過程,該過程為學(xué)生檔案表的StuId字段根據(jù)當(dāng)前StuId中的最大值自動生成一個編號,并保存到StuId字段中中,如圖7-13所示。
圖7-12 可以在項目管理器選擇建立或修改存儲過程
圖7-13 NewStuId存儲過程
執(zhí)行下面的代碼,將在學(xué)生檔案表中添加一條新記錄,并為StuId字段賦值。
APPEND BLANK
NewStuId() 執(zhí)行存儲過程
需要注意的是,如果準備存儲過程用于表的觸發(fā)器,則不能包含如圖7-13中所示的CALCULATE、GO和REPLACE這些引起記錄移動的命令。
2.從文本文件中導(dǎo)入存儲過程
可以使用APPEND PROCEDURES命令將文本文件中的存儲過程以編程的方式添加到當(dāng)前數(shù)據(jù)庫中,其語法格式如下:
APPEND PROCEDURES FROM FileName [AS nCodePage] [OVERWRITE]
其中,F(xiàn)ileName指定保存存儲過程的文本文件名稱;AS nCodePage指定要追加其存儲過程的文本文件要轉(zhuǎn)換的代碼頁;OVERWRITE指定用文本文件中的過程改寫數(shù)據(jù)庫中的當(dāng)前存儲過程,如果不包含此參數(shù),文本文件中的存儲過程將追加到當(dāng)前存儲過程中。
需要注意的是,在使用該命令前,數(shù)據(jù)庫必須以獨占方式打開并設(shè)置為當(dāng)前數(shù)據(jù)庫。
3.將存儲過程導(dǎo)出到文本文件中
可以使用COPY PROCEDURES命令將當(dāng)前數(shù)據(jù)庫中的存儲過程導(dǎo)出到文本文件,其語法格式如下:
COPY PROCEDURES TO FileName [AS nCodePage] [ADDITIVE]
其中,F(xiàn)ileName指定文本文件名,存儲過程將被復(fù)制到此文本文件中;AS nCodePage指定文本文件的代碼頁;ADDITIVE指定將存儲過程追加到指定文本文件尾,如果若省略該參數(shù),則覆蓋文本文件的內(nèi)容。
4.查看數(shù)據(jù)庫中的存儲過程
可以使用DISPLAY PROCEDURES或LIST PROCEDURES命令顯示當(dāng)前數(shù)據(jù)庫中的存儲過程名稱,二者的功能基本相同。其中,DISPLAY PROCEDURES命令的語法格式如下:
DISPLAY PROCEDURES [TO PRINTER [PROMPT] | TO FILE FileName] [NOCONSOLE]
其中,TO PRINTER [PROMPT]指定將顯示結(jié)果輸出到打印機中,包含PROMPT子句可以在打印開始前顯示一個打印對話框;TO FILE FileName指定將顯示結(jié)果輸出到FileName指定的文件中;NOCONSOLE指定不向Visual FoxPro主窗口或活動的用戶自定義窗口輸出。
例如,下面的代碼將顯示dbMyData數(shù)據(jù)庫中的存儲過程名稱。
OPEN DATABASE dbMyData
DISPLAY PROCEDURES
7.3.6 設(shè)置觸發(fā)器
觸發(fā)器是綁定在表上的表達式,當(dāng)表中的任何記錄被指定的操作命令修改時,觸發(fā)器被激發(fā)。當(dāng)數(shù)據(jù)修改時,觸發(fā)器可執(zhí)行數(shù)據(jù)庫應(yīng)用程序要求的任何其他操作。
觸發(fā)器作為特定表的屬性來創(chuàng)建和存儲。如果從數(shù)據(jù)庫中移去一個表,則同時刪除和該表相關(guān)聯(lián)的觸發(fā)器。從前面的表7-7可以看出,觸發(fā)器是在進行了其他所有檢查之后(如有效性規(guī)則、主關(guān)鍵字的實施,以及NULL值的實施)被激活,位于所有約束的最后面。并且與字段級規(guī)則和記錄級規(guī)則不同,觸發(fā)器不對緩沖數(shù)據(jù)起作用。
1.建立觸發(fā)器
可以使用表設(shè)計器或CREATE TRIGGER命令來創(chuàng)建觸發(fā)器。對于每個表,可為插入、更新及刪除3個事件各創(chuàng)建一個觸發(fā)器。在任何情況下,一個表最多只能有3個觸發(fā)器。觸發(fā)器必須返回“真”(.T.)或“假”(.F.),只有返回“真”時操作才能繼續(xù)進行。能夠激發(fā)觸發(fā)器的命令如表7-9所示。
表7-9 能夠激發(fā)觸發(fā)器的命令
觸發(fā)器
命令
刪除觸發(fā)器
DELETE命令
插入觸發(fā)器
APPEND FROM、APPEND FROM ARRAY、APPEND BLANK、IMPORT、INSERT-SQL和RECALL命令
序表
觸發(fā)器
命令
更新觸發(fā)器
GATHER、REPLACE、REPLACE FROM ARRAY和UPDATE SQL命令
需要注意的是,不能對有觸發(fā)器的表使用INSERT命令,但是可以使用INSERT-SQL命令;發(fā)出PACK或ZAP不會激發(fā)任何觸發(fā)器;如果更新具有刪除標(biāo)記的記錄,不會激發(fā)觸發(fā)器;如果表使用了緩沖模式,只有當(dāng)使用TABLEUPDATE( )函數(shù)進行發(fā)送更新時,才激發(fā)更新觸發(fā)器。
下面是在dbMyData數(shù)據(jù)庫中建立的4個存儲過程。其中,InsertData用于在添加記錄時顯示一個“新增記錄…”提示;UpdateData用于在記錄更新時自動將更新記錄寫入到一個日志表tblStudent2中,來記錄用戶對學(xué)生檔案表所做的修改;DeleteData用于在刪除記錄時顯示一個信息框,詢問用戶是否確認刪除記錄;WriteLog用于寫入日志,該過程可以接收來自UpdateData過程的參數(shù)傳入值。
PROCEDURE WriteLog
PARAMETERS lcStuId,lcStuName,lcClassName,ldEnterDate,lnChinese,lnMaths,lnTotal
*!* 將變動寫入到日志表tblStuden2中
INSERT INTO tblStudent2 (StuId,StuName,ClassName,EnterDate,Chinese,Maths,Total) ;
VALUES (lcStuId,lcStuName,lcClassName,ldEnterDate,lnChinese,lnMaths,lnTotal)
PROCEDURE InsertData
WAIT WINDOW "新增記錄..." NOWAIT TIMEOUT 2
RETURN .T.
PROCEDURE UpdateData
WAIT WINDOW "正在將變動寫入日志表..." NOWAIT TIMEOUT 2
WriteLog(StuId,StuName,ClassName,EnterDate,Chinese,Maths,Total)
RETURN .T.
PROCEDURE DeleteData
IF MESSAGEBOX("確認刪除該記錄嗎?",4+32," 提示")=6
RETURN .T.
ELSE
RETURN .F.
ENDIF
打開表設(shè)計器,在Table選項卡的Insert trigger、Update trigger和Delete trigger文本框中分別輸入InsertData()、UpdateData()和DeleteData(),如圖7-14所示。
圖7-14 為表建立觸發(fā)器
也可以使用CREATE TRIGGER命令為表建立觸發(fā)器表達式,該命令的語法格式如下:
CREATE TRIGGER ON TableName FOR DELETE | INSERT | UPDATE AS lExpression
其中,TableName是要建立觸發(fā)器的表名稱,lExpression是觸發(fā)器表達式。例如,下面使用該命令為學(xué)生檔案表建立了與圖7-14同樣的觸發(fā)器表達式。
OPEN DATABASE dbMyData
CREATE TRIGGER ON 學(xué)生檔案表 FOR INSERT AS InsertData() 建立插入觸發(fā)器
CREATE TRIGGER ON 學(xué)生檔案表 FOR UPDATE AS UpdateData() 建立更新觸發(fā)器
CREATE TRIGGER ON 學(xué)生檔案表 FOR DELETE AS DeleteData() 建立刪除觸發(fā)器
2.刪除觸發(fā)器
可以在表設(shè)計器的Table選項卡中刪除觸發(fā)器或使用DELETE TRIGGER命令從數(shù)據(jù)庫表中刪除觸發(fā)器。其中,DELETE TRIGGER命令的語法格式如下:
DELETE TRIGGER ON TableName FOR DELETE | INSERT | UPDATE
其中,TableName是要刪除觸發(fā)器的表名稱。
例如,下面的代碼將刪除學(xué)生檔案表中的插入觸發(fā)器。
DELETE TRIGGER ON 學(xué)生檔案表 FOR INSERT
3.修改觸發(fā)器
可以在表設(shè)計器的Table選項卡中或者使用CREATE TRIGGER命令來修改觸發(fā)器。使用命令修改觸發(fā)器與建立觸發(fā)器時相同。
問題一:SQL 中存儲過程怎么使用? sql存儲過程及應(yīng)用
一、簡介:
存儲過程(Stored Procedure), 是一組為了完成特定功能的SQL 語句,集經(jīng)編譯后
存儲在數(shù)據(jù)庫中,用戶通過指定存儲過程的名字并給出參數(shù),如果該存儲過程帶有參數(shù)來執(zhí)行
它,
在SQL Server 的系列版本中,存儲過程分為兩類:系統(tǒng)提供的存儲過程和用戶自定義存儲過程
。
系統(tǒng)SP,主要存儲master 數(shù)據(jù)庫中,并以sp_為前綴并且系統(tǒng)存儲過程主要是從系統(tǒng)表中獲取
信息,從而為系統(tǒng)管理員管理SQL Server。用戶自定義存儲過程是由用戶創(chuàng)建,并能完成
某一特定功能,如:查詢用戶所需數(shù)據(jù)信息的存儲過程。
存儲過程具有以下優(yōu)點
1.存儲過程允許標(biāo)準組件式編程(模塊化設(shè)計)
存儲過程在被創(chuàng)建以后,可以在程序中被多次調(diào)用,而不必重新編寫該存儲過程的SQL語句,而
且數(shù)
據(jù)庫專業(yè)人員可隨時對存儲過程進行修改,但對應(yīng)用程序源代碼毫無影響。因為應(yīng)用程序源代
碼只包含存
儲過程的調(diào)用語句,從而極大地提高了程序的可移植性。
2.存儲過程能夠?qū)崿F(xiàn)快速的執(zhí)行速度
如果某一操作包含大量的Transaction-SQL 代碼,,或分別被多次執(zhí)行,那么存儲過程要比批處理
的
執(zhí)行速度快很多,因為存儲過程是預(yù)編譯的,在首次運行一個存儲過程時,查詢優(yōu)化器對其進
行分析優(yōu)
化,并給出最終被存在系統(tǒng)表中的執(zhí)行計劃,而批處理的Transaction-SQL 語句在每次運行時
都要進行
編譯和優(yōu)化,因此速度相對要慢一些。
3.存儲過程能夠減少網(wǎng)絡(luò)流量
對于同一個針對數(shù)據(jù)數(shù)據(jù)庫對象的操作,如查詢修改,如果這一操作所涉及到的Transaction-SQL
語句被組織成一存儲過程,那么當(dāng)在客戶計算機上調(diào)用該存儲過程時,網(wǎng)絡(luò)中傳送的只是該調(diào)
用語句,否
則將是多條SQL 語句從而大大增加了網(wǎng)絡(luò)流量降低網(wǎng)絡(luò)負載。
4.存儲過程可被作為一種安全機制來充分利用
系統(tǒng)管理員通過,對執(zhí)行某一存儲過程的權(quán)限進行限制,從而能夠?qū)崿F(xiàn)對相應(yīng)的數(shù)據(jù)訪問權(quán)限的
限
制。
二、變量
@I
三、流程控制語句(if else | select case | while )
Select ... CASE 實例
DECLARE @iRet INT, @PKDisp VARCHAR(20)
SET @iRet = '1'
Select @iRet =
CASE
WHEN @PKDisp = '一' THEN 1
WHEN @PKDisp = '二' THEN 2
WHEN @PKDisp = '三' THEN 3
WHEN @PKDisp = '四' THEN 4
WHEN @PKDisp = '五' THEN 5
ELSE 100
END
四、存儲過程格式
創(chuàng)建存儲過程
Create Proc dbo.存儲過程名
存儲過程參數(shù)
AS
執(zhí)行語句
RETURN
執(zhí)行存儲過程
GO
*********************************************************/
-- 變量的聲明,sql里面聲明變量時必須在變量前加@符號
DECLARE @I INT
-- 變量的賦值,變量賦值時變量前必須加set
SET @I = 30
-- 聲明多個變量
DECLARE @s varchar(10),@a INT
-- Sql 里if語句
IF 條件 BEGIN
執(zhí)行語句
END
ELSE BEGIN
......
問題二:為什么要使用存儲過程? 幾個去 IBM 面試的兄弟回來抱怨:去了好幾個不同的 IBM項目組,幾乎每個面試官問到數(shù)據(jù)庫的時候都要問用沒用過存儲過程,煩人不?大家去面的程序員,又不是筆者認為,存儲過程說白了就是一堆 SQL 的合并。中間加了點邏輯控制。但是存儲過程處理比較復(fù)雜的業(yè)務(wù)時比較實用。比如說,一個復(fù)雜的數(shù)據(jù)操作。如果你在前臺處理的話。可能會涉及到多次數(shù)據(jù)庫連接。但如果你用存儲過程的話。就只有一次。從響應(yīng)時間上來說有優(yōu)勢。也就是說存儲過程可以給我們帶來運行效率提高的好處。另外,程序容易出現(xiàn) BUG數(shù)據(jù)量小的,或者和錢沒關(guān)系的項目不用存儲過程也可以正常運作。mysql 的存儲過程還有待實際測試。如果是正式項目,建議你用 sqlserver 或 oracle的存儲過程。數(shù)據(jù)與數(shù)據(jù)之間打交道的話,過程會比程序來的快的多。面試官問有沒有用存儲,實際上就是想知道前來面試的程序員到底做過數(shù)據(jù)量大的項目沒。如果是培訓(xùn)出來的,或者小項目小公司出來的,對存儲肯定接觸的少了。所以,要想進大公司,沒有豐富存儲過程經(jīng)驗,是不行的。錯。存儲過程不僅僅適用于大型項目,對于中小型項目,使用存儲過程也是非常有必要的。其威力和優(yōu)勢主要體現(xiàn)在:1.存儲過程只在創(chuàng)造時進行編譯,以后每次執(zhí)行存儲過程都不需再重新編譯,而一般 SQL語句每執(zhí)行一次就編譯一次,所以使用存儲過程可提高數(shù)據(jù)庫執(zhí)行速度。2.當(dāng)對數(shù)據(jù)庫進行復(fù)雜操作時(如對多個表進行Update,Insert,Query,Delete時),可將此復(fù)雜操作用存儲過程封裝起來與數(shù)據(jù)庫提供的事務(wù)處理結(jié)合一起使用。這些操作,如果用程序來完成,就變成了一條條的 SQL語句,可能要多次連接數(shù)據(jù)庫。而換成存儲,只需要連接一次數(shù)據(jù)庫就可以了。3.存儲過程可以重復(fù)使用,可減少數(shù)據(jù)庫開發(fā)人員的工作量。4.安全性高,可設(shè)定只有某此用戶才具有對指定存儲過程的使用權(quán)?!〈鎯^程的缺點1:調(diào)試麻煩,但是用 PL/SQL Developer 調(diào)試很方便!彌補這個缺點。 2:移植問題,數(shù)據(jù)庫端代碼當(dāng)然是與數(shù)據(jù)庫相關(guān)的。但是如果是做工程型項目,基本不存在移植問題。 3:重新編譯問題,因為后端代碼是運行前編譯的,如果帶有引用關(guān)系的對象發(fā)生改變時,受影響的存儲過程、包將需要重新編譯(不過也可以設(shè)置成運行時刻自動編譯)。4:如果在一個程序系統(tǒng)中大量的使用存儲過程,到程序交付使用的時候隨著用戶需求的增加會導(dǎo)致數(shù)據(jù)結(jié)構(gòu)的變化,接著就是系統(tǒng)的相關(guān)問題了,最后如果用戶想維護該系統(tǒng)可以說是很難很難、而且代價是空前的。維護起來更加麻煩!
問題三:oracle中的存儲過程,有什么作用,以及怎么在代碼中使用? 樓上也不知道從哪扒下來的,一看LZ就是初學(xué),舉點例子不行嗎?
比如建立個測試表
create table test(id int,name varchar2(10),counts int); insert into test values (1,'張三',100);insert into test values (2,'李四',200); mit;
現(xiàn)在給你出個題目是
查詢所有人加在一起的counts是多少
創(chuàng)建存儲過程
create or replace p_test --創(chuàng)建存儲過程,asv_counts int;--定義變量begin --開始select sum(counts) into v_counts from test;--將得到的結(jié)果放到變量里DBMS_OUTPUT.PUT_LINE(v_counts);--將結(jié)果打印輸出end;--結(jié)束
執(zhí)行這種不帶輸入?yún)?shù)的
begin p_test;end;
然后你檢查下結(jié)果
再給你創(chuàng)建一個帶輸入?yún)?shù)的
題目是,查詢id為1的人名是什么
create or replace p_test1(v_id int)asv_name varchar2(10);beginselect name into v_name from test where id=v_id;DBMS_OUTPUT.PUT_LINE(v_name);end;
執(zhí)行時這樣
beginp_test1(1);end;
第2個我沒給你寫注釋,你看你自己應(yīng)該能理解吧
補充一下,存儲過程不一定只是執(zhí)行查詢,也可以做刪除或者修改等sql語句,總體來說就是幾個或N個sql語句的 *** ,來完成系統(tǒng)內(nèi)某些特定的需求,這些需求可以是一個sql搞定的,也可以是多個sql組合的
問題四:SQL 存儲過程建立和使用方法? Sql Server的存儲過程是一個被命名的存儲在服務(wù)器上的Transacation-Sql語句 *** ,是封裝重復(fù)性工作的一種方法,它支持用戶聲明的變量、條件執(zhí)行和其他強大的編程功能。 存儲過程相對于其他的數(shù)據(jù)庫訪問方法有以下的優(yōu)點: (1)重復(fù)使用。存儲過程可以重復(fù)使用,從而可以減少數(shù)據(jù)庫開發(fā)人員的工作量。 (2)提高性能。存儲過程在創(chuàng)建的時候就進行了編譯,將來使用的時候不用再重新編譯。一般的SQL語句每執(zhí)行一次就需要編譯一次,所以使用存儲過程提高了效率。 (3)減少網(wǎng)絡(luò)流量。存儲過程位于服務(wù)器上,調(diào)用的時候只需要傳遞存儲過程的名稱以及參數(shù)就可以了,因此降低了網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量。 (4)安全性。參數(shù)化的存儲過程可以防止SQL注入式的攻擊,而且可以將Grant、Deny以及Revoke權(quán)限應(yīng)用于存儲過程。 存儲過程一共分為了三類:用戶定義的存儲過程、擴展存儲過程以及系統(tǒng)存儲過程。 其中,用戶定義的存儲過程又分為Transaction-SQL和CLR兩種類型。 Transaction-SQL 存儲過程是指保存的Transaction-SQL語句 *** ,可以接受和返回用戶提供的參數(shù)。 CLR存儲過程是指對.Net Framework公共語言運行時(CLR)方法的引用,可以接受和返回用戶提供的參數(shù)。他們在.Net Framework程序集中是作為類的公共靜態(tài)方法實現(xiàn)的。(本文就不作介紹了) 創(chuàng)建存儲過程的語句如下:Code
CREATE { PROC | PROCEDURE } [schema_name.] procedure_name [ ; number ]
[ { @parameter [ type_schema_name. ] data_type }
[ VARYING ] [ = default ] [ [ OUT [ PUT ]
] [ ,n ]
[ WITH [ ,n ]
[ FOR REPLICATION ]
AS { [;][ n ] | }
[;]
::=
[ ENCRYPTION ]
[ REPILE ]
[ EXECUTE_AS_Clause ]
::=
{ [ BEGIN ] statements [ END ] }
::=
EXTERNAL NAME assembly_name.class_name.method_name [schema_name]: 代表的是存儲過程所屬的架構(gòu)的名稱 例如: Create Schema yangyang8848
Go
Create Proc yangyang8848.AllGoods
As Select * From Master_Goods
Go 執(zhí)行:Exec AllGoods 發(fā)生錯誤。 執(zhí)......
問題五:數(shù)據(jù)庫中的存儲過程怎么用 ?。?!求解..... 10分 關(guān)鍵字:procedure
例子:
SQL create [or replace] procedure procedure_name is
begin
--開始執(zhí)行
insert into test('10001','Visket');
end;
/
以上操作就能為test表添加一條信息
執(zhí)行存儲過程procedure用的命令是exec
記住存儲過程中,語句結(jié)尾一定要有分號
問題六:存儲過程是多用還是少用? 做項目的時候我們有時候會面臨一個選擇,我們到底是應(yīng)該多寫存儲過程還是少寫存儲過程了?這個問題的爭論也是由來已久,在不同的公司以及不同的技術(shù)負責(zé)人那里往往會得到不同的答案。在實際項目中我們最后所采取的方式,往往不外乎以下三種方式。
第一種方式是要求所有數(shù)據(jù)庫操作不使用任何的存儲過程,所有操作都采用標(biāo)準sql語句來完成,即便是一個動作需要完成多步數(shù)據(jù)庫操作,也不使用任何存儲過程,而是在程序代碼中采用事務(wù)的方式來完成;第二種方式就是就要求所有的數(shù)據(jù)庫操作都用存儲過程封裝起來,哪怕是一個最簡單的insert 操作。在程序代碼看不到一行 sql語句,如果采用分工合作的方式,程序員甚至都可以不懂sql語法。第三種方式是一般相對簡單的數(shù)據(jù)庫操作采用標(biāo)準sql語句來完成,一些相對比較復(fù)雜的商務(wù)邏輯用存儲過程來完成。
當(dāng)然系統(tǒng)如果采用了hibernate或nhibernate之類的框架,不需要寫sql語句的時候,我想還是應(yīng)該屬于第三種方式,因為在開發(fā)的時候hibernate框架允許我們在適當(dāng)?shù)臅r候,拋開其框架自己寫存儲過程和sql語句來完成數(shù)據(jù)庫操作。其實這三種方式都各有所長,也各有不足。
第一種方式是所有的數(shù)據(jù)庫操作都采用標(biāo)準sql語句來完成的方式,在程序的執(zhí)行效率上是肯定不如后面兩種方式,系統(tǒng)如果是一個大型的ERP,這種方式就是絕對不可取的。因為在開發(fā)基本結(jié)束后,系統(tǒng)如果需要優(yōu)化或者希望得到優(yōu)化時,那對開發(fā)人員來說就是一件非常麻煩的事情了,因為優(yōu)化的重點基本上都是集中數(shù)據(jù)庫操作上,開發(fā)人員所能做的就是一個個sql語句去檢查,是不是還能進一步優(yōu)化,尤其是一些相對比較復(fù)雜的查詢語句是我們所檢查的重點。分頁顯示就是一個典型的存儲過程提高程序效率的例子。如果使用存儲過程來進行分頁操作,就是利用存儲過程從系統(tǒng)中提取我們所需要的記錄集,分頁的效率就大大提高了。反過來如果我們不用存儲過程進行分頁操作,是利用sql語句的方式把所有記錄集都讀入內(nèi)存中,然后再從內(nèi)存中獲取我們所需要的記錄 *** ,這樣分頁效率自然就降低了。當(dāng)然利用sql語句也能得到我們所需要的記錄,而不是所有記錄,但是那樣麻煩多了,不在我們討論范圍之內(nèi)。
這種方式另外還有一個不足之處,一個系統(tǒng)或一個項目總會或多或少地存在有一些容易變化而又復(fù)雜的商務(wù)邏輯,如果把這些復(fù)雜的商務(wù)邏輯封裝到存儲過程中,商務(wù)邏輯的變化都只涉及存儲過程變化,而與程序代碼不 *** ,那么不用存儲過程太可惜了。
這種方式雖然有不足,但是一旦采用這種方式的話,我們?nèi)绻麑υ擁椖窟M行數(shù)據(jù)庫移植的時候,開發(fā)人員就會覺得當(dāng)時的決策人是多么的偉大與英明。而且我們知道access和mysql的以前版本是不提供存儲過程支持的,所有一些中小項目在這個方面的選擇往往也是不得已而為之。不用存儲過程有一個優(yōu)點,調(diào)試代碼的時候沒有存儲過程可是要方便很多很多的哦,所以在很多很多的項目中都是采用標(biāo)準的sql語句而不使用任何的存儲過程。這可是大多程序員用標(biāo)準sql而不用存儲過程的直接原因,說白了,就是嫌麻煩。
第二種方式是所有的數(shù)據(jù)庫操作全部采用存儲過程封裝的方式,如果采用這種方式,程序的執(zhí)行效率相對要高,尤其面對在一些復(fù)雜的商務(wù)邏輯時候,不僅在效率方面有明顯的提高,而且當(dāng)商務(wù)邏輯發(fā)生變化時,我們開發(fā)人員做相應(yīng)的修改的時候,往往都不用修改程序代碼,僅僅修改存儲過程就能滿足系統(tǒng)變化了。
還有一個好處就是當(dāng)我們開發(fā)好的一個系統(tǒng)后,如果發(fā)現(xiàn)一種模式或語言在某些方面難以滿足需求時,我們就可以很快的用兩外一種語言來重新開發(fā),那個時候就非常方便了。比如在02年中科院下屬的一個公司就用ASP開......
問題七:在SQL中存儲過程的一般語法是什么? sql server存儲過程語法
存儲過程就是作為可執(zhí)行對象存放在數(shù)據(jù)庫中的一個或多個SQL命令。
定義總是很抽象。存儲過程其實就是能完成一定操作的一組SQL語句,只不過這組語句是放在數(shù)據(jù)庫中的(這里我們只談SQL Server)。如果我們通過創(chuàng)建存儲過程以及在ASP中調(diào)用存儲過程,就可以避免將SQL語句同ASP代碼混雜在一起。這樣做的好處至少有三個:
第一、大大提高效率。存儲過程本身的執(zhí)行速度非常快,而且,調(diào)用存儲過程可以大大減少同數(shù)據(jù)庫的交互次數(shù)。
第二、提高安全性。假如將SQL語句混合在ASP代碼中,一旦代碼失密,同時也就意味著庫結(jié)構(gòu)失密。
第三、有利于SQL語句的重用。
在ASP中,一般通過mand對象調(diào)用存儲過程,根據(jù)不同情況,本文也介紹其它調(diào)用方法。為了方便說明,根據(jù)存儲過程的輸入輸出,作以下簡單分類:
1. 只返回單一記錄集的存儲過程
假設(shè)有以下存儲過程(本文的目的不在于講述T-SQL語法,所以存儲過程只給出代碼,不作說明):
/*SP1*/
CREATE PROCEDURE dbo.getUserList
as
set nocount on
begin
select * from dbo.[userinfo]
end
go
以上存儲過程取得userinfo表中的所有記錄,返回一個記錄集。通過mand對象調(diào)用該存儲過程的ASP代碼如下:
'**通過mand對象調(diào)用存儲過程**
DIM Mym,MyRst
Set Mym = Server.CreateObject(ADODB.mand)
Mym.ActiveConnection = MyConStr 'MyConStr是數(shù)據(jù)庫連接字串
Mym.mandText = getUserList '指定存儲過程名
Mym.mandType = 4 '表明這是一個存儲過程
Mym.Prepared = true '要求將SQL命令先行編譯
Set MyRst = Mym.Execute
Set Mym = Nothing
存儲嘩程取得的記錄集賦給MyRst,接下來,可以對MyRst進行操作。
在以上代碼中,mandType屬性表明請求的類型,取值及說明如下:
-1 表明mandText參數(shù)的類型無法確定
1 表明mandText是一般的命令類型
2 表明mandText參數(shù)是一個存在的表名稱
4 表明mandText參數(shù)是一個存儲過程的名稱
還可以通過Connection對象或Recordset對象調(diào)用存儲過程,方法分別如下:
'**通過Connection對象調(diào)用存儲過程**
DIM MyConn,MyRst
Set MyConn = Server.CreateObject(qu......
問題八:如何使用Oracle存儲過程的一個簡單例子 樓主您好
---創(chuàng)建表
create table TESTTABLE
(
id1 VARCHAR2(12),
name VARCHAR2(32)
)
select t.id1,t.name from TESTTABLE t
insert into TESTTABLE (ID1, NAME)
values ('1', 'zhangsan');
insert into TESTTABLE (ID1, NAME)
values ('2', 'lisi');
insert into TESTTABLE (ID1, NAME)
values ('3', 'wangwu');
insert into TESTTABLE (ID1, NAME)
values ('4', 'xiaoliu');
insert into TESTTABLE (ID1, NAME)
values ('5', 'laowu');
---創(chuàng)建存儲過程
create or replace procedure test_count
as
v_total number(1);
begin
select count(*) into v_total from TESTTABLE;
DBMS_OUTPUT.put_line('總?cè)藬?shù):'||v_total);
end;
--準備
--線對scott解鎖:alter user scott account unlock;
--應(yīng)為存儲過程是在scott用戶下。還要給scott賦予密碼
---alter user scott identified by tiger;
---去命令下執(zhí)行
EXECUTE test_count;
----在ql/spl中的sql中執(zhí)行
begin
-- Call the procedure
test_count;
end;
create or replace procedure TEST_LIST
AS
---是用游標(biāo)
CURSOR test_cursor IS select t.id1,t.name from TESTTABLE t;
begin
for Test_record IN test_cursor loop---遍歷游標(biāo),在打印出來
DBMS_OUTPUT.put_line(Test_record.id1||Test_record.name);
END LOOP;
test_count;--同時執(zhí)行另外一個存儲過程(TEST_LIST中包含存儲過程test_count)
end;
-----執(zhí)行存儲過程TEST_LIST
begin
TEST_LIST;
END;
---存儲過程的參數(shù)
---IN 定義一個輸入?yún)?shù)變量,用于傳遞參數(shù)給存儲過程
--OUT 定義一個輸出參數(shù)變量,用于從存儲過程獲取數(shù)據(jù)
---IN OUT 定義一個輸入、輸出參數(shù)變量,兼有以上兩者的功能
......
問題九:如何使用sql語句查看存儲過程 --下面這條語句可以查看存儲過程具體代碼exec sp_helptext 存儲過程名--下面這條語句查看數(shù)據(jù)庫中有哪些存儲過程select * from sysobjects where type='P'
問題十:存儲過程中怎么使用row 一般分為十種情況,每種語法各不相同: 1、 創(chuàng)建語法create proc | procedure pro_name [{@參數(shù)數(shù)據(jù)類型} [=默認值] [output], {@參數(shù)數(shù)據(jù)類型} [=默認值] [output], .... ]as SQL_statements2、 創(chuàng)建不帶參數(shù)存儲過程--創(chuàng)建存儲過程if (exists (select * from sys.objects where name = 'proc_get_student')) drop proc proc_get_studentgocreate proc proc_get_studentas select * from student;--調(diào)用、執(zhí)行存儲過程exec proc_get_student;3、 修改存儲過程--修改存儲過程alter proc proc_get_studentasselect * from student;4、 帶參存儲過程--帶參存儲過程if (object_id('proc_find_stu', 'P') is not null) drop proc proc_find_stugocreate proc proc_find_stu(@startId int, @endId int)as select * from student where id between @startId and @endIdgoexec proc_find_stu 2, 4;5、 帶通配符參數(shù)存儲過程--帶通配符參數(shù)存儲過程if (object_id('proc_findStudentByName', 'P') is not null) drop proc proc_findStudentByNamegocreate proc proc_findStudentByName(@name varchar(20) = '%j%', @nextName varchar(20) = '%')as select * from student where name like @name and name like @nextName;goexec proc_findStudentByName;exec proc_findStudentByName '%o%', 't%';6、 帶輸出參數(shù)存儲過程if (object_id('proc_getStudentRecord', 'P') is not null) drop proc proc_getStudentRecordgocreate proc proc_getStudentRecord( @id int, --默認輸入?yún)?shù) @name varchar(20) out, --輸出參數(shù) @age varchar(20) output--輸入輸出參數(shù))as select @name = name, @age = age from student where id = @id and sex = @age;go-- declare @id int, @name varchar(20), @temp varchar(20)......
網(wǎng)頁題目:存儲過程轉(zhuǎn)go語言 go 對象存儲
標(biāo)題來源:http://chinadenli.net/article24/dodejje.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、品牌網(wǎng)站制作、云服務(wù)器、網(wǎng)站建設(shè)、動態(tài)網(wǎng)站、網(wǎng)站策劃
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)