Από τότε που γράφτηκε το Δυναμικό pass SQL με χρήση EXEC και μετά από αυτά που μας...έσουρε (με το δίκιο του) ο Pkanavos, έψαχνα να βρώ τροπο να εκτελέσω ένα αναθεματισμένο select έχοντας στο χέρι μου μόνο ένα delimited string με IDs. Αυτό που έκανα μέχρι τώρα ήταν το εξής: Εφτιαχνα μια stored procedure η οποία δεχόταν σαν παράμετρο ένα varchar(1000) π.χ., και μετά έτρεχα ένα EXEC που ήταν π.χ. κάπως έτσι:
EXEC 'SELECT a,b,c FROM mytable WHERE myfield IN (' + @myparam +')'
Ωσπου άναψε ένα λαμπάκι πάνω από το κεφάλι μου και σκέφτηκα οτι μπορώ να το κάνω κι αλλιώς. Για την ακρίβεια άλλος το σκέφτηκε, εγώ το...ανακάλυψα.
Εδω λοιπόν μπορείτε να βρείτε ένα σχετικό αρθράκι. Παραθέτω τον κώδικα δημιουργίας μιας UDF, όπως αναφέρει το άρθρο, που δέχεται ένα delimited string με αριθμους (υποθέτουμε οτι έχουμε ints), και δημιουργεί ένα πίνακα μιας στήλης με τους αριθμούς αυτούς έτσι ωστε να μπορέσουμε να τον κάνουμε join στον αρχικό:
Να σημειώσω οτι την παραθέτω αυτούσια, όπως αναφέρεται στο άρθρο. Σιγουρα σηκώνει βελτιώσεις, αλλα δεν ήθελα να την πειράξω.
Create Function dbo.CsvToInt ( @Array varchar(1000))
returns @IntTable table
(IntValue int)
AS
begin
declare @separator char(1)
set @separator = ','
declare @separator_position int
declare @array_value varchar(1000)
set @array = @array + ','
while patindex('%,%' , @array) <> 0
begin
select @separator_position = patindex('%,%' , @array)
select @array_value = left(@array, @separator_position - 1)
Insert @IntTable
Values (Cast(@array_value as int))
select @array = stuff(@array, 1, @separator_position, '')
end
return
end
Εχοντας αυτή την function μπορεί κανείς πρακτικά να καταργήσει το dynamic SQL του μια και μπορεί πλέον να κάνει το εξής:
SELECT a, b, c
FROM mytable
INNER JOIN dbo.CsvToInt ('1,34,433,3') tblkeys
ΟΝ mytable.myid = tblkeys.IntValue
Χρήσιμο. Βεβαια παραμένει το πρόβλημα της απόδοσης, αλλά τουλάχιστον δεν έχουμε EXEC statements.
Σωτήρης Φιλιππίδης
DotSee Web Services