Đối với các thông số đầu vào và đầu ra, bạn có thể nhìn vào sys.parameters
, sys.procedures
và sys.types
. Đây là một quy trình với các thông số đầu vào / đầu ra khác nhau, các loại bí danh và thậm chí cả TVP (chỉ có trên 2008):
USE [tempdb];
GO
CREATE TYPE dbo.TVPType AS TABLE(id INT);
GO
CREATE PROCEDURE dbo.foobar
@a INT,
@b SYSNAME = N'foo',
@c DATETIME = NULL,
@d dbo.TVPType READONLY,
@e NVARCHAR(MAX),
@f INT OUTPUT,
@g INT = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT @f = COUNT(*) FROM sys.objects;
END
GO
Và đây là một truy vấn để lấy thông tin này từ sys.parameters
, sys.procedures
và sys.types
:
SELECT
s = QUOTENAME(OBJECT_SCHEMA_NAME(p.[object_id])),
o = QUOTENAME(p.name),
p = pr.name,
t1.name,
pr.max_length,
pr.[precision],
pr.scale,
pr.is_output,
pr.is_readonly
FROM sys.procedures AS p
INNER JOIN sys.parameters AS pr
ON p.[object_id] = pr.[object_id]
LEFT OUTER JOIN sys.types AS t1
ON (pr.system_type_id = t1.system_type_id)
AND (pr.system_type_id <> t1.system_type_id
OR pr.user_type_id = t1.user_type_id)
WHERE p.[object_id] = OBJECT_ID('dbo.foobar')
ORDER BY pr.parameter_id;
Các kết quả:
s o p name max_length [precision] scale is_output is_readonly
----- ---------- --- -------- --------- ----------- ----- --------- -----------
[dbo] [foobar] @a int 4 10 0 0 0
[dbo] [foobar] @b sysname 256 0 0 0 0
[dbo] [foobar] @c datetime 8 23 3 0 0
[dbo] [foobar] @d TVPType -1 0 0 0 1
[dbo] [foobar] @e nvarchar -1 0 0 0 0
[dbo] [foobar] @f int 4 10 0 1 0
[dbo] [foobar] @g int 4 10 0 1 0
Rõ ràng bạn cần thực hiện một số thao tác xoa bóp để có được các giá trị đó trông giống như các kiểu dữ liệu thực. Ví dụ, cắt max_length của nvarchar một nửa, trừ khi nó là -1, trong trường hợp đó, nó cần được hoán đổi với MAX
. Đối với số thập phân, số, vv, thêm độ chính xác và tỷ lệ thích hợp. Nếu bạn đang sử dụng TVP, có lẽ bạn muốn lấy lược đồ sử dụng SCHEMA_NAME
cho các loại đó. Vân vân.
Thật không may, không có cách nào ngoại trừ lực lượng vũ trang phân tích cơ thể thủ tục (và thậm chí đó không phải là tầm thường nếu không có các kỹ năng RegEx ninja nghiêm túc) để xác định xem tham số này có thể là null hay không, hoặc nó có giá trị mặc định hay không và giá trị mặc định là gì. Thông tin này đơn giản là không được lưu trữ trong siêu dữ liệu - trong khi có has_default_value
và default_value
các cột trong đó sys.parameters
, chúng chỉ bao giờ khác NULL
hoặc không bằng 0 đối với các thủ tục CLR. Tôi đã phàn nàn về điều này từ năm 2006, nhưng chúng tôi vẫn chưa thấy bất kỳ tiến bộ nào trong lĩnh vực này (mặc dù tôi đã đăng một cách giải quyết về mục Kết nối mà tôi sẽ không sao chép ở đây vì nó đưa ra một số giả định vô lý về phong cách mã hóa của các thủ tục được lưu trữ của bạn). Và không có gì cả thậm chí còn mang lại bất kỳ hy vọng nào để xác định xem tham số có phải là tùy chọn không (ví dụ @c
và @g
ở trên).
Đối với các tập kết quả, Martin hoàn toàn đúng - không có cách nào mạnh mẽ để tìm ra kết quả sẽ bao gồm ngoại trừ việc sử dụng SET FMTONLY ON
. Có một số lỗi đặc biệt với cái này, vì vậy tôi sẽ tránh xa nó. Loại bùn phổ biến là sử dụng OPENQUERY
với máy chủ được liên kết "loopback" , chọn kết quả vào bảng #temp, nhưng điều này chỉ hoạt động nếu quy trình có chính xác một kết quả. Một ví dụ điển hình tồn tại trong một trong những câu trả lời trước của Martin:
Cách dễ nhất để tạo bảng tạm thời trong SQL Server có thể giữ kết quả của một thủ tục được lưu trữ là gì?
Khi bạn đã đặt đầu ra vào bảng #temp, bạn có thể thực thi:
EXEC tempdb..sp_help '#tablename';
Điều này sẽ xuất ra, trong số những thứ khác, một danh sách các tên cột và kiểu dữ liệu của chúng. Mặc dù đây sẽ là một quá trình tẻ nhạt để thực hiện cho hàng trăm thủ tục được lưu trữ, tôi có ý tưởng về cách tự động hóa nó vì vậy nếu đây có vẻ là một giải pháp thú vị cho bạn, vui lòng cho tôi biết và tôi có thể mở rộng câu trả lời của mình.
Martin cũng ám chỉ chức năng mới trong SQL Server 2012 sẽ giúp việc này dễ dàng hơn rất nhiều (nhưng nó vẫn bị giới hạn trong tập kết quả đầu tiên của một thủ tục được lưu trữ). Bạn có thể xem thêm chi tiết về điều đó trong câu trả lời của tôi cho cùng một câu hỏi ở trên.
Đối với các giá trị trả về, tôi không biết cách nào để lấy chúng từ siêu dữ liệu.