2010-06-15 62 views
10

在SQL查詢中使用'goto'語句是否是一種好的做法?sql-goto語句

+9

http://xkcd.com/292/ – ircmaxell 2010-06-15 14:18:41

+1

@ircmaxell我的情緒。 – Meiscooldude 2010-06-15 14:20:07

+0

SQL中沒有'GOTO' - 只有T-SQL – 2017-03-10 06:52:47

回答

8

取決於SQL--一些方言不提供GOTO以外流量控制的有用機制。

GOTO通常是不好的形式。

0

我的猜測是否定的。我使用任何現代語言的goto語句的一般規則是,如果您使用它們,那麼您的設計出現問題。

3

與其他語言中,幾乎總是一個更好的選擇比轉到使用。

如果您告訴我們您正在使用哪個SQL軟件包以及您想要完成的工作,我們可能會爲您提供一個確切的解決方案。

+0

這是一個由某人編寫的存儲過程。 – SoftwareGeek 2010-06-15 15:38:48

+0

@BhejaFry - 但它是T-SQL,PL-SQL,MySQL等嗎? – 2010-06-15 18:34:28

+0

它是T-SQL,會不會pl-sql支持goto? – SoftwareGeek 2010-06-16 01:15:44

5

沒有在生產代碼,但測試可能是好的。

例如,希望爲存儲過程提供迴歸測試,其中「常用位」是對正在測試的過程和調試語句的調用。

declare @test int; 
set @test = 1; 
goto tests 

common: 
print "common bit" 

tests: 
if @test = 1 print "1"; 
if @test = 2 print "2"; 
if @test = 3 print "3"; 

set @test = @test + 1; 
if @test <= 3 goto common 
print "finished " + cast(@test as varchar(5)) 
go -- goto can not be used past go! 

是T-SQL小白我希望的過程或函數範圍內聲明做了「公共位」,但是,這是我能想出經過多次使用Google最好的。爲什麼你需要爲你想要重複使用的每一位代碼設置一個存儲過程。特別適用於非生產性工作。

+0

您在使用GOTO使用小功能時提出了一個很好的觀點。 :-)我們需要T-SQL中的Lambda表達式! ;-) – 2013-07-26 12:42:55

0

goto是關鍵字有它自己的功能。 只要需要跳轉到某個級別,我們就可以使用goto。

讓我們看看例子... 在我的存儲過程中,我需要使用4個臨時表中的數據。 在臨時表中插入記錄之後,我需要檢查記錄是否存在於此臨時溫度中,如果沒有記錄插入,而不是進一步處理,我可以使用goto直接跳轉。 標籤是我們應該跳出了這一點:究竟

CREATE TABLE #tmpMsNos (custPo CHAR(24)) 

    CREATE TABLE #tmpValidBilltos (billto CHAR(12)) 

    CREATE TABLE #tmpOrders (
     fh_pkey INT 
     ,fh_id CHAR(8) 
     ,custPo CHAR(24) 
     ,lastchOfCustInsert DATETIME 
     ) 

    CREATE TABLE #tmpOrdersFiltered (
     fh_pkey INT 
     ,fh_id CHAR(8) 
     ,custPo CHAR(24) 
     ,lastchOfCustInsert DATETIME 
     ,onbDate DATETIME 
     ,rapDate DATETIME 
     ) 

    CREATE TABLE #tmpLoad (
     custPo CHAR(24) 
     ,ld_pkey INT 
     ,ld_wkpmpn CHAR(25) 
     ,lda_barcode VARCHAR(30) 
     ,ld_createdOn DATETIME 
     ,ReceivedDate DATETIME 
     ,DispatchedDate DATETIME 
     ) 

INSERT INTO #tmpMsNos 
    SELECT cast(itemValue AS CHAR(24)) 
    FROM dbo.fn_array_to_table(@pMsNos, ',') 

IF (
      NOT EXISTS (
       SELECT 1 
       FROM #tmpMsNos 
       ) 
      ) 
    BEGIN 
     GOTO label 
    END 
INSERT INTO #tmpValidBilltos 
    SELECT CONVERT(CHAR(12), xm_doref) 
    FROM xmlref x 
    WHERE xm_element = 'THD-BoxtruckRequest' 
     AND xm_attribute = 'THD-BoxtruckBillto' 

IF (
      NOT EXISTS (
       SELECT 1 
       FROM #tmpValidBilltos 
       ) 
      ) 
    BEGIN 
     GOTO label 
    END 

INSERT INTO #tmpOrders 
    SELECT fh.fh_pkey 
     ,fh.fh_id 
     ,fh.fh_custPo 
     ,max(coc.ch_dt) 
    FROM #tmpMsNos msNos 
    INNER JOIN fcfgthd fh ON msNos.custPo = fh.fh_custPo 
    INNER JOIN #tmpValidBilltos bt ON bt.billto = fh.fh_bt_id 
    LEFT JOIN chofcust coc ON coc.ch_fhpkey = fh.fh_pkey 
    WHERE fh.fh_statcode NOT IN (
      98 --CAN 
      ,99 --DEL 
      ) 
     AND fh.fh_ship_dt > @startDate 
    GROUP BY fh.fh_pkey 
     ,fh.fh_id 
     ,fh.fh_custPo 

    IF (
      NOT EXISTS (
       SELECT 1 
       FROM #tmpOrders 
       ) 
      ) 
    BEGIN 
     GOTO label 
    END 

INSERT INTO #tmpOrdersFiltered 
    SELECT t.fh_pkey 
     ,t.fh_id 
     ,t.custPo 
     ,t.lastchOfCustInsert 
     ,MAX(cocONB.ch_dt) 
     ,MAX(cocRAP.ch_dt) 
    FROM (
     SELECT tmpO.fh_pkey 
      ,tmpo.fh_id 
      ,tmpO.custPo 
      ,tmpO.lastchOfCustInsert 
     FROM #tmpOrders tmpO 
     INNER JOIN (
      SELECT custpo 
       ,max(lastchOfCustInsert) AS MaxInserteddate 
      FROM #tmpOrders 
      GROUP BY custpo 
      ) tmpOgrouped ON tmpO.custpo = tmpOgrouped.custpo 
      AND tmpO.lastchOfCustInsert = tmpOgrouped.MaxInserteddate 
     ) AS t 
    LEFT JOIN chofcust cocRAP ON cocRAP.ch_fhpkey = t.fh_pkey 
     AND cocRAP.ch_stat = 2 -- RAP --TODO: Add comment with status code like 98, 99 -- CAN, DEL for readability - Paresh 
    LEFT JOIN chofcust cocONB ON cocONB.ch_fhpkey = t.fh_pkey 
     AND cocONB.ch_stat = 5 -- ONB --TODO: Add comment with status code like 98, 99 -- CAN, DEL for readability - Paresh 
    GROUP BY t.fh_pkey 
     ,t.fh_id 
     ,t.custPo 
     ,t.lastchOfCustInsert 

    --TODO: Take an exit if no order found into #tmpOrdersFiltered table, while taking a early exit make sure it doesn't break the calling code (C#) - Paresh 
    IF (
      NOT EXISTS (
       SELECT 1 
       FROM #tmpOrdersFiltered 
       ) 
      ) 
    BEGIN 
     GOTO label 
    END 
INSERT INTO #tmpLoad 
    SELECT o.custPo 
     ,l.ld_pkey 
     ,l.ld_wkpmpn 
     ,la.lda_barcode 
     ,max(coc.ch_dt) 
     ,CASE ISNULL(w.xl_date, '') 
      WHEN '' 
       THEN o.rapDate 
      ELSE w.xl_date 
      END AS ReceivedDate 
     ,CASE ISNULL(mm.me_ecpkey, '') 
      WHEN '' 
       THEN o.ONBDate 
      ELSE NULL 
      END AS DispatchedDate 
    FROM #tmpOrdersFiltered o 
    INNER JOIN fcload l ON l.ld_fhpkey = o.fh_pkey 
    LEFT JOIN loadanc la ON la.lda_ldpkey = l.ld_pkey 
    LEFT JOIN wkxaclog w ON w.xl_ldpkey = l.ld_pkey 
    LEFT JOIN multiexceps mm ON mm.me_ldpkey = l.ld_pkey 
     AND mm.me_ecpkey = @missingitemexcep 
    LEFT JOIN chofcust COC ON coc.ch_ldpkey = l.ld_pkey 
     AND coc.ch_stat = 64 -- 64= ILH 
    GROUP BY o.custPo 
     ,l.ld_pkey 
     ,l.ld_wkpmpn 
     ,la.lda_barcode 
     ,w.xl_date 
     ,o.rapDate 
     ,mm.me_ecpkey 
     ,o.ONBDate