Otrzymujemy listę zamówień i sprawdzamy, czy zaczyna się od określonych prefiksów, na przykład jeśli numer zamówienia nie zaczyna się od ABC, to wyświetla zamów listę dla użytkownika jako błąd. Używamy istnieje, aby wyszukać pierwsze istnienie, nie chcemy zużywać dużo czasu na wydajność. Jeśli żadne nie istnieje, możemy rozpocząć wykonywanie innego zadania w kodzie.
Czy jest w sql, aby się pozbyć powtarzający się kod? Mamy wiele takich sprawdzeń na wielu tabelach, próbując uczynić kod bardziej wydajnym.
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
Odpowiedź
Niestety, obawiam się, że próbując zapobiec powtarzaniu kodu, możesz napisać więcej kodu i sprawić, że zapytanie będzie mniej czytelne. Ale uważam, że może to być dla Ciebie korzystne – weź pod uwagę sytuacje, w których w teście musiałbyś szukać tylko w jednej lub dwóch tabelach, gdzie aby odzyskać wszystkie szczegóły, będziesz musiał dołączyć do kilku kolejnych. W takich sytuacjach możesz uprościć zapytanie testowe, dzięki czemu będą one szybsze do wykonania.
A skoro już o tym mowa, możesz również rozważyć zmianę instrukcji WHERE. Użycie funkcji w predykacie powoduje, że nie są one SARGable i zapobiega używaniu indeksów w takich przypadkach. Lepszym podejściem w tym przykładzie byłoby sprawdzenie
WHERE OrderNumber LIKE "ABC%"
, ponieważ optymalizator wykona konwersję na coś podobnego do
OrderNumber >= "ABC" AND OrderNumber < "ABD"
, który obsługuje użycie indeksów. Więc to byłoby skanowanie indeksu (przy użyciu left ()) w porównaniu z wyszukiwaniem indeksu (przy użyciu LIKE).
Odpowiedź
Niestety, dla z różnych powodów (nie tylko starszych) SQL nie ma prawie wszystkich opcji ponownego wykorzystania kodu i funkcji, które ma większość języków klienta, a niektóre z nich (jak skalarne UDF) mają poważne problemy. Więc w dużej mierze, jeśli chcesz być efektywnym programistą SQL, musisz zrezygnować z wykonywania o wiele więcej ponownego wykorzystania kodu typu „wytnij i wklej”, niż kiedykolwiek rozważałbyś w języku klienta, takim jak C #, VB. Net lub Java.
To powiedziawszy, możesz wyeliminować nadmiarowość w swoim przykładzie, jednak niezależnie od tego, czy jest lepsza, czy nie, musisz zdecydować.
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
Komentarze
- Czy mógłbyś to jeszcze bardziej uprościć, zaznaczając @@ ROWCOUNT zamiast istnieje?
- @mathewb Tak, ale należy to zrobić natychmiast po INSERT..SELECT. Jeśli dodasz kolejne stwierdzenie, nagle przestaje działać poprawnie i staram się unikać takich min w moich odpowiedziach. Rozwiązaniem byłoby zapisanie @@ ROWCOUNT w zmiennej, ale wtedy nie byłoby to znacznie lepsze niż to, co mam powyżej.
Odpowiedź
Czy w sql jest sposób na pozbycie się powtarzającego się kodu?
Niezupełnie, nie. Możesz przeformułować zapytanie w ten sposób, bez instrukcji IF, ale tak naprawdę nie różni się ono od tego, co masz:
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 )