If Exists – Select Prevent Repeating Code

Dostaneme seznam objednávek a ověří to, že začíná určitými předponami, například pokud OrderNumber nezačíná ABC, než display seznam objednávek uživateli jako chyba. Používáme existující, k vyhledání první existence nechceme spotřebovávat mnoho času na výkon. Pokud žádný neexistuje, můžeme začít provádět další úlohy v kódu.

Existuje nějak v sql, jak se zbavit opakující se kód? Máme mnoho kontrol, jako je tento, na více tabulkách a snažíme se zefektivnit kód.

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 

Odpovědět

Bohužel se bojím pokusu zabránit opakování kódu, který by mohl skončit napsáním více kódu a snížením čitelnosti dotazu. Ale věřím, že to pro vás může být výhodné – vezměte v úvahu situace, kdy byste v testu museli hledat pouze v jedné nebo dvou tabulkách, kde se pro získání všech podrobností budete muset připojit k několika dalším. V těchto situacích můžete testovací dotaz zjednodušit a tím také zrychlit jejich provádění.

A když už jsme u toho, můžete také zvážit změnu svého příkazu WHERE. Používání funkcí v predikátu je činí SARGable a v těchto případech zabrání použití indexů. Lepším přístupem v tomto příkladu by bylo zkontrolovat

WHERE OrderNumber LIKE "ABC%" 

, protože optimalizátor provede převod na něco v duchu

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

který podporuje použití indexů. Toto by bylo indexové skenování (pomocí left ()) versus Index Seek (pomocí LIKE).

Odpověď

Bohužel pro řada důvodů (nejen starší) SQL nemá téměř všechny možnosti a funkce opětovného použití kódu, které má většina klientských jazyků, a některé z nich (například skalární UDF) mají značné problémy. Takže do značné míry, pokud chcete být efektivním programátorem SQL, musíte rezignovat na to, abyste provedli mnohem více opětovného použití kódu pro vystřihování a vkládání, než byste někdy považovali v klientském jazyce, jako je C #, VB. Síť nebo Java.

To znamená, že ve svém příkladu můžete eliminovat nadbytečnost, ale ať už je to skutečně lepší nebo ne, budete se muset rozhodnout.

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 

Komentáře

  • Mohli byste to ještě zjednodušit zaškrtnutím @@ ROWCOUNT místo toho, aby existovalo?
  • @mathewb Ano, ale musí to být provedeno ihned po VLOŽENÍ..VÝBĚR. Pokud přidáte další prohlášení, najednou přestane fungovat správně a já se ve svých odpovědích snažím vyhnout takovým minám. Řešením by bylo uložit @@ ROWCOUNT do proměnné, ale pak by to nebylo výrazně lepší než to, co mám výše.

Odpovědět

Existuje vůbec v sql zbavit se opakujícího se kódu?

Ne tak docela, ne. Dotaz můžete přeformulovat takto bez příkazu IF, ale ve skutečnosti se neliší od toho, co máte:

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 ) 

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *