Hvis der findes – Vælg Forhindre gentagelseskode

Vi modtager en ordreliste, og validerer den starter med visse præfikser, f.eks. Hvis OrderNumber ikke starter med ABC, end display ordreliste til bruger som fejl. Vi bruger eksisterer, for at søge efter første eksistens, vil ikke forbruge meget præstationstid. Hvis der ikke findes nogen, kan vi begynde at udføre en anden opgave i kode.

Er der alligevel i sql at slippe af med den gentagne kode? Vi har mange kontroller som denne på flere tabeller, hvor vi prøver at gøre koden mere effektiv.

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

Desværre er jeg bange ved at forsøge at forhindre gentagelse af kode, kan du ende med at skrive mere kode og gøre forespørgslen mindre læselig. Men jeg mener, at dette kan være en fordel for dig – tag højde for situationer, hvor du i testen kun skulle søge i en eller to tabeller, hvor du for at hente alle detaljerne bliver nødt til at deltage i flere flere. I disse situationer kan du forenkle testforespørgslen og dermed gøre dem hurtigere at udføre.

Og mens vi er ved det, kan du også overveje at ændre din WHERE-sætning. Brug af funktioner i prædikatet gør dem ikke SARGable og forhindrer brug af indekser i disse tilfælde. En bedre tilgang i dette eksempel ville være at kontrollere

WHERE OrderNumber LIKE "ABC%" 

da optimeringsprogrammet udfører konvertering til noget i retning af

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

som understøtter brugen af indekser. Så dette ville være indeksscanning (ved hjælp af venstre ()) versus indekssøgning (ved hjælp af LIKE).

Svar

Desværre for af forskellige årsager (ikke kun arv) SQL har ikke næsten alle de kode genbrugsmuligheder og funktioner, som de fleste klientsprog har, og nogle af dem (som skalære UDFer) har betydelige problemer. Så i vid udstrækning, hvis du vil være en effektiv SQL-programmør, er du nødt til at give afkald på at gøre meget mere klip-og-indsæt kodeanvendelse, end du nogensinde ville overveje på et klientsprog som C #, VB. Net eller Java.

Når det er sagt, kan du fjerne redundansen i dit eksempel, men uanset om det faktisk er bedre eller ej, skal du beslutte.

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

  • Kunne du forenkle dette yderligere ved at kontrollere @@ ROWCOUNT i stedet for eksisterer?
  • @mathewb Ja, men det skal gøres straks efter INSERT..SELECT. Hvis du tilføjer en ny erklæring, holder den pludselig op med at fungere korrekt, og jeg prøver at undgå landminer sådan i mine svar. Løsningen ville være at gemme @@ ROWCOUNT i en variabel, men så ville det ikke være væsentligt bedre end hvad jeg har ovenfor.

Svar

Er der alligevel i sql at slippe af med den gentagne kode?

Ikke rigtig, nej. Du kan omformulere forespørgslen som denne uden IF-udsagnet, men det adskiller sig ikke rigtig fra det, 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 ) 

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *