ตารางที่มีค่าพารามิเตอร์เป็นพารามิเตอร์ผลลัพธ์สำหรับกระบวนงานที่เก็บไว้


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

คำตอบ:


35

ไม่โชคไม่ดีที่ค่าพารามิเตอร์ของตารางเป็นแบบอ่านอย่างเดียวและป้อนเข้าเท่านั้น โดยทั่วไปหัวข้อนี้ได้รับการคุ้มครองเป็นอย่างดีในวิธีการแบ่งปันข้อมูลระหว่างขั้นตอนการจัดเก็บซึ่งนำเสนอทางเลือกทั้งหมด คำแนะนำของฉันจะใช้#tempตาราง


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

นอกจากคำตอบที่ใส่ไว้อย่างดีจากรีมัสรวมถึงลิงก์ที่เขาให้ไว้

วิธีการแบ่งปันข้อมูลระหว่างขั้นตอนการจัดเก็บ

มีสถานการณ์ที่คุณได้รับข้อความแสดงข้อผิดพลาดต่อไปนี้เมื่อบันทึกผลลัพธ์ของกระบวนงานที่เก็บไว้ในตาราง:

คำสั่ง INSERT EXEC ไม่สามารถซ้อนกันได้

ธุรกรรมปัจจุบันไม่สามารถกระทำได้และไม่สามารถรองรับการดำเนินการที่เขียนไปยังล็อกไฟล์ ย้อนกลับการทำธุรกรรม

และเมื่อสิ่งนี้เกิดขึ้นในขั้นตอนการจัดเก็บของฉันเองที่ฉันพัฒนาเพื่อการใช้งานเอง

เช่นเครื่องมือที่จะบอกฉันจากloginกลุ่มโฆษณาทั้งหมดที่เป็นของและสิทธิ์ทั้งหมดในฐานข้อมูลทั้งหมดในเซิร์ฟเวอร์

ฉันสร้างตาราง temp นอกโพรซีเดอร์และส่งชื่อเป็นพารามิเตอร์

--===============
-- 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)

หลังจากนั้นคุณมีข้อมูลที่คุณต้องการบนหน้าจอหรือถ้าคุณผ่านตาราง temp เป็นพารามิเตอร์มันจะมีข้อมูลทันที

นี้เป็นวิธีการแก้หนึ่งที่ผมพบ แต่ฉันเท่านั้นที่ใช้สำหรับการทำงานของตัวเองDBAมิฉะนั้นจะถือว่ามีความเสี่ยงสูงสำหรับSQL Injection

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.