Làm thế nào để xác định giá trị đầu vào và đầu ra của các thủ tục được lưu trữ?


7

Tôi có hàng trăm SP và tôi muốn tìm hiểu:

  • tham số đầu vào với loại
  • trường đầu ra với loại (không phải tham số đầu ra)

Tất nhiên tôi có thể tự mình đi qua từng người và viết nó ra nhưng đâu là niềm vui trong đó ... Không, nghĩa đen là nơi nào là niềm vui trong đó :)

Điều này có thể được thực hiện hay Sql Management Studio 2008 R2 đã có khả năng này chưa?

Tôi thậm chí không biết bắt đầu từ đâu nên bất kỳ câu trả lời nào cũng được chấp nhận.

Chỉnh sửa để cải thiện câu hỏi: Nếu chúng ta xem nó như 2 nhiệm vụ khác nhau, chúng ta có thể thực hiện việc này dễ dàng hơn không. Ngay cả việc sử dụng sự phản ánh ở phía khách hàng. (Một ứng dụng bảng điều khiển nhanh và bẩn sẽ đủ.)


1
"Trường đầu ra" nghĩa là gì? Bạn đang nói về các tham số đầu ra hoặc các cột trong (các) tập kết quả?
Martin Smith

Sự khác biệt là gì? Tôi có thể có cả hai cùng một lúc không? Tất cả những gì tôi thực sự quan tâm là loại dữ liệu nào tôi sẽ nhận được. Tôi là người mới trong thuật ngữ. Tôi nghĩ rằng cột còn được gọi là các lĩnh vực. Nhưng như Mary tuyên bố, tôi có nghĩa là "các cột trong tập kết quả". :)
Michael Wells

1
cột và các lĩnh vực khá đồng nghĩa. Lý do cho câu hỏi là vì bạn đã đề cập rõ ràng các tham số đầu vào nên không chắc chắn liệu bạn có ý định tham khảo các tham số đầu ra ở đó hay không. Hiện tại không có cách nào tốt để có được danh sách cột (và có thể có nhiều hơn một tập kết quả hoặc hình dạng của nó có thể thay đổi theo mã thủ tục trong Proc). Visual Studio thực hiện nó bằng cách SET FMTONLY ON;và thực hiện các thủ tục được lưu trữ. SQL Server 2012 có một số chức năng bổ sung sẽ giúp ở đây.
Martin Smith

Thông số đầu ra là gì?
Michael Wells

1
Các tham số được trang trí với outputtừ khóa có thể được gán trong Proc và giá trị được lấy bởi người gọi thủ tục được lưu trữ. Hữu ích khi bạn muốn truyền lại các giá trị vô hướng thay vì các hàng dữ liệu. Chúng thực sự là các tham số đầu vào / đầu ra ở chỗ chúng cũng có thể được sử dụng để truyền các giá trị vào thủ tục.
Martin Smith

Câu trả lời:


4

Bạn sẽ có thể làm điều đó bằng cách sử dụng chế độ xem hệ thống Information_SCHema.PARAMETERS . Bạn sẽ có những gì bạn cần.

Nó "trả về một hàng cho mỗi tham số của hàm do người dùng xác định hoặc thủ tục được lưu trữ mà người dùng hiện tại có thể truy cập trong cơ sở dữ liệu hiện tại. Đối với các hàm, chế độ xem này cũng trả về một hàng với thông tin giá trị trả về."

PS: nếu câu trả lời cho câu hỏi của Martin là "các cột trong tập kết quả", thì hãy bỏ qua câu trả lời của tôi, nó chỉ dành cho các tham số của quy trình, không dành cho bất kỳ kết quả nào.


3

Đố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.proceduressys.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.proceduressys.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_NAMEcho 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_valuedefault_valuecác cột trong đó sys.parameters, chúng chỉ bao giờ khác NULLhoặ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@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 OPENQUERYvớ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.


Cảm ơn bạn đã viết và giải thích mọi thứ. Không biết sests kết quả là gì, nó có phải là một bộ dữ liệu với nhiều datatables?
Michael Wells

Kết quả đặt từ SELECTtruy vấn lên đầu? Bạn đã chạy nó (chỉ thay đổi tên của thủ tục để tìm kiếm)? Đó là một tập kết quả duy nhất chứa một hàng cho mỗi tham số (nó sẽ chỉ trở thành "dữ liệu" nếu bạn sử dụng nó trong .NET và biến nó thành như vậy).
Aaron Bertrand

Tất cả những gì tôi thực sự cần là một cách nhanh chóng để ghi lại các SP ban đầu của chúng tôi và xác định xem liệu có bất kỳ trả về dữ liệu / số vô hướng trùng lặp hay không. Tôi không tin rằng chúng ta chỉ có một số ít trả về nhiều dữ liệu trong một tập dữ liệu. Tôi đã xuất các thông số đầu vào cho các SP và hàm của chúng tôi sang bảng tính excel nhưng chưa có bộ dữ liệu kết quả. Tôi thích ý tưởng tự động hóa mà bạn đề cập và tôi không có vấn đề gì về việc xoa bóp dữ liệu. Tôi đã suy nghĩ về việc viết một chương trình để lấy danh sách SP và các hàm và chuyển từng truy vấn vào một truy vấn để tạo danh sách các tham số đầu vào và sử dụng
Michael Wells

phản ánh trên tập dữ liệu kết quả để có được tên cột và kiểu dữ liệu. Tôi nghĩ rằng tôi có thể thử truy vấn SQL của bạn để tạo đầu ra và sau đó xoa bóp nó trên đường chuyền thứ hai.
Michael Wells

À, tôi hiểu rồi. Xin lỗi, nhưng như tôi đã đề xuất, thực sự không có cách nào để phát hiện các bản sao trong tập kết quả mà không biết phạm vi giá trị đầu vào cho các quy trình và chạy chúng.
Aaron Bertrand
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.