2010-06-03 30 views
13

Tôi có một truy vấn SQL tham số được nhắm mục tiêu cho SQL2005 được tạo động trong mã, vì vậy tôi đã sử dụng lớp ADO.NET SqlParameter để thêm tham số sql vào SqlCommand.Làm thế nào để bạn chỉ định 'DEFAULT' làm giá trị tham số SQL trong ADO.NET?

Trong SQL nói trên tôi chọn từ một hàm có giá trị bảng có mặc định. Tôi muốn sql động của tôi đôi khi chỉ định một giá trị cho các tham số mặc định này, và các thời điểm khác tôi muốn xác định rằng SQL DEFAULT - như được định nghĩa trong hàm Table Valued - nên được sử dụng.

Để giữ mã sạch Tôi không muốn tự động thêm từ khóa SQL DEFAULT và parameterize nó khi không mặc định được sử dụng, tôi chỉ muốn thiết lập DEFAULT như giá trị của SQLParameter tôi.

Tôi có thể? Thực hành tốt nhất trong ví dụ này là gì?

+1

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 ... –

+2

@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. –

+0

@Bill Karwin: Thx, chắc chắn là tin cho tôi. –

Trả lời

11

Tham số truy vấn SQL thay thế các giá trị theo nghĩa đen chỉ. Bạn không thể gửi một từ khóa SQL làm giá trị của một tham số, cũng giống như bạn không thể gửi một định danh bảng, mã định danh cột, danh sách các giá trị (ví dụ: đối với vị từ IN) hoặc một biểu thức. Giá trị của thông số là luôn là được hiểu là giá trị bằng chữ, như thể bạn đã bao gồm một chuỗi ký tự được trích dẫn hoặc một chữ số trong truy vấn của bạn.

Xin lỗi, nhưng bạn phải bao gồm từ khóa SQL như một phần của truy vấn SQL trước bạn chuẩn bị truy vấn đó.

+0

Vâng, nó là một con số thấp.Tôi hiểu lý do tại sao nhưng chỉ làm cho mọi thứ một chút dính cho tôi :) – Llyle

+3

Cũng trong các thủ tục được lưu trữ nếu bạn đặt 'SqlParameter.Value' thành' null', nó sẽ tự động gửi giá trị 'default' tới SQL Server. Nếu bạn muốn đặt trường cơ sở dữ liệu thành 'null', hãy sử dụng' DBNull.Value'. – Jalal

+0

@Jalal, cảm ơn, đó là một mẹo hay! –

4

AFAIK, cách duy nhất để yêu cầu SQL Server sử dụng giá trị mặc định là thông qua từ khóa DEFAULT hoặc loại trừ từ danh sách tham số. Điều đó có nghĩa là việc sử dụng từ khóa DEFAULT phải nằm trong Tuyên bố SQL được tham số hóa của bạn. Vì vậy, một cái gì đó như:

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

Tôi cho rằng cách tiếp cận khác sẽ được truy vấn catalog hệ thống cho các giá trị thực tế của DEFAULT giá trị khác nhau và xác định xem có nên thiết lập các SqlParameter với giá trị mặc định theo cách đó, nhưng điều đó đòi hỏi phải có một truy vấn thứ hai phức tạp để có được các giá trị mặc định.

-1

nếu bạn chuyển giá trị vô giá trị của dấu chấm ròng làm giá trị tham số, nó sẽ sử dụng sql DEFAULT nếu bạn vượt qua DBNull chấm chấm.Giá trị nó sẽ sử dụng sql NULL

+1

-1 Điều này không đúng. Khi gọi một thủ tục được lưu trữ trong ngữ cảnh 'SqlCommand.CommandType = CommandType.Text', bạn có thể chỉ ra rằng một tham số có giá trị mặc định thực sự nên sử dụng mặc định bằng cách không xác định tham số, không cài đặt, hoặc thiết lập nó 'null' như trong' SqlParameter.Value = null; '. Nhưng điều này không giống với việc sử dụng T-SQL 'DEFAULT' (câu hỏi này là gì). Nó giống như gọi proc mà không có param. Và câu hỏi này dành riêng cho TVF, không phải các thủ tục được lưu trữ và TVF không cho phép không chỉ định tất cả các tham số đầu vào. –

+0

Bạn có biết nếu có thể vượt qua DEFAULT ** thông qua tham số ** với cuộc gọi TVF không? Nghiên cứu của tôi cho biết không, không thể, bạn phải phát hiện không có giá trị nào được chỉ định và thay thế bằng tay @ParameterName trong chính SqlText bằng DEFAULT. Đó là niềm tin hiện tại của tôi. – tbone

+0

@srutzky Đó là bạn – tbone

2

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.

+1

Vấn đề với điều này là nó giả định rằng [null] ngụ ý [mặc định], mà có thể không phải lúc nào cũng đúng. Vấn đề này là một thiếu sót thực sự trong việc thực hiện của Microsoft. – tbone

0

Mặc dù bạn không thể đặt từ khóa SQL làm giá trị của một tham số, bạn có thể trong trường hợp này đi và nhận giá trị DEFAULT VALUE.

SELECT COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS 
     WHERE TABLE_NAME = 'table_name' AND COLUMN_NAME = 'column_name'" 
Các vấn đề liên quan