Come si specifica 'DEFAULT' come valore di parametro SQL in ADO.NET?
-
24-10-2019 - |
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 ??em> 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?
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