Nếu bạn có các chức năng sau đây (ví dụ):
CREATE FUNCTION dbo.UFN_SAMPLE_FUNCTION
(
@Param1 nvarchar(10),
@Param2 int = NULL
)
RETURNS TABLE
AS
RETURN
SELECT @Param1 AS Col1, @Param2 AS Col2;
GO
Sau đó, bạn có thể sử dụng nó theo cách sau (tùy chọn 1):
SELECT * FROM dbo.UFN_SAMPLE_FUNCTION ('ABC', DEFAULT);
đó là đúng cách và bạn nhận được kết quả sau:
Col1 Col2
---------- -----------
ABC NULL
Nhưng nếu bạn cố gắng sử dụng truy vấn parametrized (opti trên 2):
exec sp_executesql N'SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)',N'@P1 nvarchar(10),@P2 int',@P1=N'abc',@P2=default;
bạn sẽ nhận được một lỗi:
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.
Nếu bạn có mã .net sau:
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())
{
//...
}
}
}
}
sau đó, trong trường hợp param2 = null như Jack đề nghị ở trên, tập lệnh được tạo bởi mã sẽ giống hệt với tùy chọn 2 và sẽ dẫn đến lỗi tương tự. Vì vậy, bạn không thể sử dụng NULL trong trường hợp này.Bạn không thể đặt DEFAULT làm giá trị của SQLParameter.
Những gì bạn có thể làm là tạo một thủ tục lưu sẵn để gói cuộc gọi đến funcion của bạn và di chuyển giá trị mặc định của bạn từ hàm này sang SP. Ví dụ:
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',@[email protected],@[email protected];
END
Mã NET sẽ xem xét các cách sau:
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())
{
//...
}
}
}
}
Trong trường hợp này rỗng như một giá trị cho param2 sẽ được dịch sang đúng DEFAULT và tập lệnh sau sẽ được tạo:
exec USP_SAMPLE_PROCEDURE @Param1=N'ABC',@Param2=default,@Statement=N'SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)'
sẽ cung cấp cho bạn kết quả sau:
Col1 Col2
---------- -----------
ABC NULL
Tôi không chắc rằng đây là phương pháp hay nhất. Đây chỉ là công việc.
Từ khóa "DEFAULT" SQL? Có ràng buộc mặc định, cho phép bạn đặt giá trị mặc định trong trường hợp không được cung cấp cho cột ... –
@OMG Ngựa vằn: Bạn có thể sử dụng 'DEFAULT' trong' INSERT' (hoặc 'UPDATE') tuyên bố giống như bạn có thể sử dụng 'NULL':' INSERT INTO foo (col1, col2) GIÁ TRỊ (1234, DEFAULT) '. Đây là SQL tiêu chuẩn nhưng ít được biết đến. –
@Bill Karwin: Thx, chắc chắn là tin cho tôi. –