Om det finns – Välj Förhindra upprepad kod

Vi får en orderlista och validerar den börjar med vissa prefix, till exempel om OrderNumber inte börjar med ABC, än display orderlista till användaren som fel. Vi använder existerar, för att söka efter första existens, vill inte konsumera mycket prestationstid. Om ingen finns, kan vi börja utföra andra uppgifter i kod.

Finns det ändå i sql att bli av med den repetitiva koden? Vi har många kontroller så här på flera tabeller, för att försöka effektivisera koden.

if exists ( select * from dbo.OrdersImport where left(OrderNumber,3) <> "ABC" ) begin select OrderNumber as OrderErrorList from dbo.OrdersImport where left(OrderNumber,3) <> "ABC" end else 

Svar

Tyvärr är jag rädd genom att försöka förhindra att kod upprepas kan det hända att du skriver mer kod och gör frågan mindre läsbar. Men jag tror att detta kan vara fördelaktigt för dig – ta hänsyn till situationer där du i testet bara skulle behöva söka i en eller två tabeller, där du för att hämta alla detaljer måste gå med i flera till. I dessa situationer kan du förenkla testfrågan och därmed göra dem snabbare att utföra.

Och medan vi håller på med det kan du också överväga att ändra ditt WHERE-uttalande. Att använda funktioner i predikatet gör dem inte SARGable och förhindrar att man använder index i dessa fall. Ett bättre tillvägagångssätt i detta exempel skulle vara att kontrollera

WHERE OrderNumber LIKE "ABC%" 

eftersom optimeraren utför konvertering till något i linje med

OrderNumber >= "ABC" AND OrderNumber < "ABD" 

som stöder användningen av index. Så detta skulle vara Index Scan (med vänster ()) kontra Index Seek (med LIKE).

Svar

Tyvärr, för olika orsaker (inte bara äldre) SQL har inte nästan alla kodåteranvändningsalternativ och funktioner som de flesta klientspråk har och några av dem (som skalära UDF: er) har betydande problem. Så i stor utsträckning, om du vill vara en effektiv SQL-programmerare, måste du avstå från att göra mycket mer klipp-och-klistra-kod-återanvändning än du någonsin skulle överväga på ett klientspråk som C #, VB. Net eller Java.

Med detta sagt kan du eliminera överflödet i ditt exempel, oavsett om det faktiskt är bättre eller inte, måste du bestämma.

Declare @OrderErrorList Table(OrderNumber varchar(32)); Insert into @OrderErrorList select OrderNumber as OrderErrorList from dbo.OrdersImport where left(OrderNumber,3) <> "ABC"; if exists ( select * from @OrderErrorList ) begin select * from @OrderErrorList end else 

Kommentarer

  • Kan du förenkla detta ytterligare genom att markera @@ ROWCOUNT istället för existerar?
  • @mathewb Ja, men det måste göras omedelbart efter INSERT..SELECT. Om du lägger till ett nytt uttalande så slutar det plötsligt att fungera korrekt och jag försöker undvika sådana landminor i mina svar. Lösningen skulle vara att spara @@ ROWCOUNT i en variabel, men då skulle det inte vara betydligt bättre än vad jag har ovan.

Svar

Finns det ändå i sql för att bli av med den repetitiva koden?

Inte riktigt, nej. Du kan omformulera frågan så här utan IF-uttalandet, men det skiljer sig inte riktigt från vad du har:

SELECT * FROM dbo.OrdersImport o WHERE LEFT(OrderNumber, 3) <> "ABC" AND EXISTS ( SELECT * FROM dbo.OrdersImport WHERE LEFT(OrderNumber,3) <> "ABC" AND ID = o.ID ) 

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *