Domanda

Ho un con parametri query SQL mirato per SQL2005 che viene creato dinamicamente nel codice, quindi ho usato la classe ADO.NET SqlParameter aggiungere parametri SQL per SqlCommand.

In SQL di cui sopra ho selezionate da una tabella funzione con valori di default con ha. Voglio che il mio SQL dinamico a volte specificare un valore per questi parametri di default, e altre volte voglio specificare che il DEFAULT SQL - come definito nella tabella funzione con valori -. Dovrebbe essere utilizzato

Per mantenere il codice pulita non volevo aggiungere dinamicamente la parola chiave SQL DEFAULT e parametrizzare quando un non predefinito deve essere utilizzato, volevo solo DEFAULT impostato come valore di il mio SQLParameter.

Posso? Qual è la cosa migliore pratica in un caso del genere?

È stato utile?

Soluzione

SQL parametri di query prendono il posto dei valori letterali solo .

Non è possibile inviare una parola chiave SQL come il valore di un parametro, così come non è possibile inviare un identificatore della tabella, identificativa della colonna, elenco di valori (ad esempio per un predicato IN), o un'espressione. Il valore del parametro è sempre interpretato come un valore letterale, come se si fosse inserito un valore letterale stringa tra virgolette o un letterale numerico nella query.

Ci dispiace, ma è necessario includere una parola chiave SQL come parte della query SQL prima si preparano quella query.

Altri suggerimenti

Per quanto ne so, l'unico modo per dire a SQL Server per utilizzare un valore di default è tramite la parola chiave DEFAULT o di escludere dalla lista dei parametri. Ciò significa che l'uso della parola chiave deve essere DEFAULT nell'istruzione SQL con parametri. Quindi, qualcosa di simile a:

Select ...
From dbo.udf_Foo( DEFAULT, @Param2, @Param3, DEFAULT, .... )

Credo che un altro approccio sarebbe quello di interrogare i cataloghi di sistema per il valore effettivo dei diversi valori DEFAULT e determinare se impostare la SqlParameter al valore di default in questo modo, ma che richiede una seconda query contorto per ottenere i valori di default.

Se si dispone la seguente funzione (per esempio):

CREATE FUNCTION dbo.UFN_SAMPLE_FUNCTION 
(
    @Param1 nvarchar(10), 
    @Param2 int = NULL
)
RETURNS TABLE
AS 
RETURN 
   SELECT @Param1 AS Col1, @Param2 AS Col2;
GO

Quindi si può utilizzare il seguente modo (opzione 1):

SELECT * FROM dbo.UFN_SAMPLE_FUNCTION ('ABC', DEFAULT);

che è il modo corretto e si ottiene il seguente risultato:

Col1       Col2
---------- -----------
ABC        NULL

Ma se si tenta di utilizzare interrogazione parametrizzata (opzione 2):

exec sp_executesql N'SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)',N'@P1 nvarchar(10),@P2 int',@P1=N'abc',@P2=default;

si otterrà un errore:

Msg 8178, Level 16, State 1, Line 0
The parameterized query '(@P1 nvarchar(10),@P2 int)SELECT * FROM dbo.UFN_SAMPLE_FUNCTION' expects the parameter '@P2', which was not supplied.

Se avete il seguente codice .net:

public void RunTVF(string param1, int? param2)
{
    using (SqlConnection con = GetProdConection())
    {
        using (var cmd = new SqlCommand("SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)", con))
        {
            cmd.CommandType = CommandType.Text;
            var param = new SqlParameter
            {
                ParameterName = "@P1",
                SqlDbType = SqlDbType.NVarChar,
                Size = 10   ,
                Value = param1
            };
            cmd.Parameters.Add(param);
            param = new SqlParameter
            {
                ParameterName = "@P2",
                SqlDbType = SqlDbType.Int,
                Value = param2
            };
            cmd.Parameters.Add(param);

            cmd.Connection.Open();
            using (IDataReader dataReader = cmd.ExecuteReader())
            {
                //...
            }
        }
    }
}

quindi, in caso param2 = null come Jack suggerito sopra, lo script prodotta dal codice sarà identica all'opzione 2 e il risultato sarà lo stesso errore. Così non si può usare NULL in questo case.You non può impostare Predefinito come valore SqlParameter sia.

Che cosa si può fare è quello di creare una stored procedure per avvolgere la chiamata alla funcion e spostare il valore di default dalla funzione per la SP. Esempio:

CREATE PROCEDURE dbo.USP_SAMPLE_PROCEDURE
( 
    @Param1 nvarchar(10), 
    @Param2 int = NULL, --DEFAULT value now is here (remove it from the function)
    @Statement nvarchar(max)
)
AS
BEGIN
    SET NOCOUNT ON;
    EXEC sp_executesql @Statement,N'@P1 nvarchar(10),@P2 int',@P1=@Param1,@P2=@Param2;
END

Il codice .NET sarà seguente modo:

public void RunWrapper(string param1, int? param2)
{
    using (SqlConnection con = GetProdConection())
    {
        using (var cmd = new SqlCommand("USP_SAMPLE_PROCEDURE", con))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            var param = new SqlParameter
            {
                ParameterName = "@Param1",
                SqlDbType = SqlDbType.NVarChar,
                Size = 10,
                Value = param1
            };
            cmd.Parameters.Add(param);
            param = new SqlParameter
            {
                ParameterName = "@Param2",
                SqlDbType = SqlDbType.Int,
                Value = param2
            };
            cmd.Parameters.Add(param);
            param = new SqlParameter
            {
                ParameterName = "@Statement",
                SqlDbType = SqlDbType.NVarChar,
                Size = -1, //-1 used in case you need to specify nvarchar(MAX)
                Value = "SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)"
            };
            cmd.Parameters.Add(param);

            cmd.Connection.Open();
            using (IDataReader dataReader = cmd.ExecuteReader())
            {
                //...
            }
        }
    }
}

In questo caso Null come valore per param2 sarà tradotto al corretto predefinito e il seguente script sarà prodotto:

exec USP_SAMPLE_PROCEDURE @Param1=N'ABC',@Param2=default,@Statement=N'SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)'

che vi darà il seguente risultato:

Col1       Col2
---------- -----------
ABC        NULL

Non sono sicuro che questo è il miglior pratica. Questo è solo il work-around.

Anche se non è possibile impostare una parola chiave SQL come il valore di un parametro, si potrebbe in questo caso andare a prendere il valore di default.

 SELECT COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS 
      WHERE TABLE_NAME = 'table_name' AND COLUMN_NAME = 'column_name'"

se si passa un puntino valore nullo netto il valore del parametro verrà utilizzato SQL predefinita se si passa un punto DBNull.Value rete userà sql NULL

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top