scottmat
Messages postés438Date d'inscriptionsamedi 24 mai 2003StatutMembreDernière intervention23 janvier 2011
-
20 juil. 2009 à 16:42
scottmat
Messages postés438Date d'inscriptionsamedi 24 mai 2003StatutMembreDernière intervention23 janvier 2011
-
20 juil. 2009 à 17:44
bonjour à tous,
j'ai une table avec 2 champs Param1 de type nvarchar et Param2 de type datetime
je souhaiterai récupérer le dernier enregistrement de la table en filtrant l'élément Param1.
j'espère que vous m'avez compris :)
voici le code en vb déjà, qui fait appel à la fonction :
Using cn As New Data.SqlClient.SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings.Item(0).ConnectionString)
Dim cmd As New Data.SqlClient.SqlCommand("Maprocedure1", cn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("@Param1", SqlDbType.NVarChar).Value = Profile.UserName
cmd.Parameters.Add("@Param2", SqlDbType.DateTime).Direction = ParameterDirection.Output
cn.Open()
Dim ret As Integer = ExecuteNonQuery(cmd)
Return CDate(cmd.Parameters("@Param2").Value)
End Using
Puis mon code SQL :
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Maprocedure1]
(
@Param1 nvarchar(256),
@Param2 datetime OUTPUT
)
AS
SET NOCOUNT ON
SELECT TOP (1) * FROM MaTable
WHERE ([Param1] = @Param1) ORDER BY [Param2] DESC
SET @Param2 = scope_identity()
mais il me dit "La conversion du type 'DBNull' en type 'Date' n'est pas valide."
l'erreur se produit au niveau de la ligne "Return CDate(cmd.Parameters("@Param2").Value)"
je me débrouille en sql mais je ne suis pas un expert non plus, j'ai modifié pas mal de truc sans arriver au résultat compté.
nivsql
Messages postés159Date d'inscriptionlundi 22 juin 2009StatutMembreDernière intervention14 décembre 20101 20 juil. 2009 à 17:14
A mon avis le probleme vient de la :
SET @Param2 = scope_identity()
vu que tu ne fais aucune insertion dans ton code je vois pas vraiment comment la fonction scope_identity() pourrait retourner autre chose que NULL !
Pour mémoire cette fonction retourne la derniere valeur identity (toute table confondue) incrémenté dans le scope (c'est a dire le périmetre) du code appelant ... vu que tu n'insert rien, aucune colone IDENTITY n'est incrémenté, donc la fonction renvoi NULL (que VB appel DBNull)
j'essayerais un truc dans ce style la :
SELECT TOP (1) @Param2 = [Param2] FROM MaTable
WHERE ([Param1] = @Param1) ORDER BY [Param2] DESC
et j'enleverais le SET qui suit le select et ne sert a rien.
nivsql
Messages postés159Date d'inscriptionlundi 22 juin 2009StatutMembreDernière intervention14 décembre 20101 20 juil. 2009 à 17:32
J'ajouterais quelques petites remarques.
J'espere que tu utilise ce genre de requete dans le contexte d'une petite table sinon ton apply est bonne pour avoir des performance de merde, voir de plomber les perf de l'instance.
En effet ta requete lis tous les lignes de MaTable correspondant a @Param1, les tri (en mémoir s'il y'en a peu, dans TempDB s'il y en a beaucoup) et filtre le premier de la liste d'ordre. Cette requete en l'état est inoptimisable et plus il y aura de lignes dans MaTable plus les performances vont se degrader. Bref ce genre de synthaxe est a oublier.
Je te conseillerais d'utiliser uniquement du code pur SQL (donc pas la clause TOP qui est une fonction de fenetrage client) en réecrivant ta requete ainsi :
SELECT @Param2 = max([Param2]) FROM MaTable
WHERE ([Param1] = @Param1)
le resultat sera identique mais le moteur SQL le rendra differament, et si MaTable devait commencer a avoir un volume important, un index sur Param1, Param2 garantirais une stabilité des performances malgrés l'augmentation du nombre de ligne.