Параметр "Табличне значення" як вихідний параметр для збереженої процедури


33

Чи можливо параметр "Табличне значення" використовувати як вихідний парам для збереженої процедури?

Ось, що я хочу зробити в коді

/*First I create MY type */
CREATE TYPE typ_test AS TABLE 
(
     id int not null
    ,name varchar(50) not null
    ,value varchar(50) not null
    PRIMARY KEY (id)
)
GO


--Now I want to create stored procedu whic is going to send output type I created, 
--But it looks like it is inpossible, at least in SQL2008
create  PROCEDURE [dbo].sp_test
         @od datetime 
        ,@do datetime 
        ,@poruka varchar(Max) output
        ,@iznos money output 
        ,@racun_stavke  dbo.typ_test   READONLY --Can I Change READONLY with OUTPUT ?
AS
BEGIN
    SET NOCOUNT ON;

    /*FILL MY OUTPUT PARAMS AS I LIKE */


    end

Відповіді:



1

Це старіший пост, але він був біля верху, коли я шукав "Параметр з табличним значенням як вихідний параметр для збереженої процедури". Хоча я розумію, що ви не можете передавати табличний параметр як вихідний параметр, я б міг уявити собі за мету використовувати цей табличний вихідний параметр як табличний вхідний параметр в іншій процедурі. Я покажу приклад того, як я зробив цю роботу.

Спочатку створіть деякі дані, з якими можна працювати:

create table tbl1
(
id int,
fname varchar(10),
gender varchar(10)
);
create table tbl2
(
id int,
lname varchar(10)
);
insert into tbl1
values
(1,'bob'  ,'m'),
(2,'tom'  ,'m'),
(3,'sally','f')
;
insert into tbl2
values
(1,'jones'   ),
(2,'johnson' ),
(3,'smith'   )
;

Далі створіть збережену процедуру для захоплення деяких даних. Як правило, саме тут ви намагаєтесь створити вихідний параметр з табличним значенням.

create procedure usp_OUTPUT1
 @gender varchar(10)
as
Begin
    select id from tbl1 where gender = @gender
End

Крім того, вам потрібно буде створити тип даних (тип таблиці), де дані з першої збереженої процедури можуть передаватися як вхідний параметр для наступної збереженої процедури.

create type tblType as Table (id int)

Далі, створіть другу збережену процедуру, яка прийме параметр, що оцінюється за таблицею.

create procedure usp_OUTPUT2
@tblType tblType readonly  --referencing the type created and specify readonly
as
begin
 select lname from tbl2 where id in (select id from @tblType)
end

Зрозуміло, це не справжній табличний параметр виходу, але він, ймовірно, дасть результати, подібні до того, що ви б шукали. Задекларуйте свій табличний параметр, заповніть його даними, виконавши в ньому збережену процедуру, а потім використовуйте його як вхідну змінну для наступної процедури.

Declare @tblType tblType 
insert into @tblType execute usp_OUTPUT1 'm'
execute usp_OUTPUT2 @tblType

1

на додаток до чудово викладеної відповіді за допомогою Remus, включаючи надане ним посилання

Як поділитися даними між збереженими процедурами

бувають ситуації, коли ви отримуєте такі повідомлення про помилки, зберігаючи результати збереженої процедури в таблицю:

Оператор INSERT EXEC не може бути вкладений.

Поточна транзакція не може бути здійснена і не може підтримувати операції, які записуються у файл журналу. Відмовити транзакцію

і коли це відбувається на моїх власних збережених процедурах, які я розробляю для власного використання

наприклад, інструмент, який повідомляє мені з loginусіх груп AD, до яких він належить, та всіх їх дозволів у всіх базах даних на сервері

Я створюю таблицю темпів поза процедурою і передаю її ім'я як параметр

--===============
-- this way below it works, by passing a temp table as a parameter
--===============

                if OBJECT_ID('tempdb.dbo.#my_table') IS NOT NULL
                   DROP TABLE #my_table

                CREATE TABLE #my_table(
                    db nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                   permission_type nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    login_  nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    role_  nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    Obj    nvarchar(517)   COLLATE Latin1_General_CI_AS  NULL,
                    Permission nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    script nvarchar(1008)  COLLATE Latin1_General_CI_AS  NULL
                ) 

                exec sp_GetLoginDBPermissionsX 
                    @Login='my_loginname', 
                    @debug=0,
                    @where_to_save ='#my_table'

                select *
                from #my_table

і всередині процедури, після всіх обчислень, коли я повертаю кінцеві дані (нижче прикладу), я перевіряю, чи ми виводимо в таблицю чи просто назад на екран і динамічно створюємо сценарій.

            select @sql = case when @where_to_save IS not null then 
            '
            insert into ' + @where_to_save + '(db,Permission_Type,login_,role_,obj,Permission,script) '
            else '' end + 
'
        SELECT 
            J.db,
            J.Permission_Type,
            J.login_,
            J.role_,
            J.Obj,
            J.Permission,
            J.script
        FROM #tablewithpermissions J
        WHERE J.login_ IN ( SELECT  L1.LOGIN_FROM COLLATE Latin1_General_CI_AS FROM #logins L1)
           OR J.role_ IN  ( SELECT  L1.LOGIN_FROM COLLATE Latin1_General_CI_AS FROM #logins L1)
       ORDER BY J.DB, J.[permission_order]
'
        --print(@sql)

        EXEC(@SQL)

Після цього у вас з'являється або необхідна інформація на екрані, або якщо ви передали тимчасову таблицю як параметр, вона тепер матиме дані.

це одне рішення я знайшов, але я використовую його лише для власних робіт, DBAінакше це вважатиметься високим ризиком для ін'єкції Sql .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.