Хорошо ли использовать операторы 'goto' в SQL-запросах?
Вывод Sql - goto
Ответ 1
Зависит от SQL - некоторые диалекты не предоставляют полезного механизма управления потоком, отличного от GOTO.
GOTO, как правило, плохая.
Ответ 2
Не в производственном коде, но для тестирования может быть хорошо.
Например, требуется предоставить регрессионное тестирование для хранимой процедуры, где "общий бит" является вызовом проверяемых процедур и отладочных инструкций.
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 noob, я надеялся, что процедура или функция объявят в рамках области действия "общий бит", но это было лучшее, что я смог придумать после многого поиска. Зачем вам нужно настраивать хранимую процедуру для каждого бит кода, который вы хотите использовать повторно. Особенно для непроизводственных работ.
Ответ 3
Нет.
Как и в других языках, почти всегда есть лучший вариант использования, чем Goto.
Если вы сообщите нам, какой пакет SQL вы используете, и что вы пытаетесь выполнить, мы можем дать вам представление о том, что именно подходит.
Ответ 4
Мое предположение было бы не так. Мое общее правило с операторами goto на любом современном языке, если вы используете их, что-то не так с вашим дизайном.
Ответ 5
goto - это ключевое слово с его собственной функцией. Мы можем использовать goto всякий раз, когда требуется перейти непосредственно на некоторый уровень.
Давайте возьмем пример... В моей хранимой процедуре мне нужно работать с данными в 4 временных таблицах. на каждом уровне после вставки записей в таблицу temp мне нужно проверить, присутствуют ли записи в этой временной или нет, если записи не были вставлены, поэтому вместо обработки я могу напрямую спрыгнуть с помощью 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