วิธีตรวจสอบว่ามีกระบวนงานที่จัดเก็บไว้แล้วหรือไม่


130

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

ฉันจะทำสิ่งนี้ใน sql ได้อย่างไร

ฉันใช้ SQL Server 2005


คำตอบ:


160

หากคุณวางและสร้างขั้นตอนคุณจะสูญเสียการตั้งค่าความปลอดภัย สิ่งนี้อาจรบกวน DBA ของคุณหรือทำให้แอปพลิเคชันของคุณเสียหายโดยสิ้นเชิง

สิ่งที่ฉันทำคือสร้างกระบวนงานที่เก็บไว้เล็กน้อยหากยังไม่มี หลังจากนั้นคุณสามารถแก้ไขขั้นตอนการจัดเก็บตามที่คุณต้องการ

IF object_id('YourSp') IS NULL
    EXEC ('create procedure dbo.YourSp as select 1')
GO
ALTER PROCEDURE dbo.YourSp
AS
...

วิธีนี้การตั้งค่าความปลอดภัยความคิดเห็นและเมตาดาต้าอื่น ๆ จะอยู่รอดจากการปรับใช้


2
อย่างน้อยถ้าคุณทำหล่นคุณรู้ว่าคุณต้องเพิ่มสิทธิ์อีกครั้ง หากคุณเรียกใช้ sql นี้คุณจะไม่ทราบว่า sproc มีสิทธิ์ที่ถูกต้องหรือไม่เนื่องจากคุณไม่ทราบว่าคุณได้สร้างหรือเปลี่ยนแปลงหรือไม่
Liazy

@Liazy วิธีแก้ปัญหาง่ายๆคือการเพิ่มรหัสในการif object_id('YourSp') is null BEGIN ... ENDเพิ่มสิทธิ์ที่เหมาะสมหลังจากสร้างขั้นตอนการจัดเก็บ
saluce

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

149

วิธีที่สะอาดที่สุดคือทดสอบการมีอยู่ปล่อยวางถ้ามีอยู่แล้วสร้างใหม่ คุณไม่สามารถฝังคำสั่ง "create proc" ไว้ในคำสั่ง IF สิ่งนี้ควรทำอย่างยิ่ง:

IF OBJECT_ID('MySproc', 'P') IS NOT NULL
DROP PROC MySproc
GO

CREATE PROC MySproc
AS
BEGIN
    ...
END

1
วิธีนี้จะได้ผล แต่จะลบการเปลี่ยนแปลงความปลอดภัยที่ใช้กับกระบวนงานที่จัดเก็บไว้
Andomar

18
การเปลี่ยนแปลงความปลอดภัยควรเป็นส่วนหนึ่งของสคริปต์เช่นกัน ด้วยวิธีนี้จะได้รับการจัดทำเอกสารอย่างถูกต้อง นี่คือแนวทางที่ถูกต้อง
Ender Wiggin

@EnderWiggin ยกเว้นหากไม่ทราบการใช้งานความปลอดภัยในขณะออกแบบ ... จะเกิดอะไรขึ้นหากผู้พัฒนาไม่ทราบว่าผู้ใช้รายใดต้องการสิทธิ์ในการดำเนินการ
Adriaan Davel

2
@AdriaanDavel l นั่นคือสิ่งที่ DBA มีไว้สำหรับและการทำให้ DBA คุยกับนักพัฒนานั้นเรียกว่าการจัดการ หากนักพัฒนาและ DBA ไม่สามารถทำงานร่วมกันได้แสดงว่า บริษัท มีปัญหา นอกจากนี้ระบบที่ใช้งานอย่างถูกต้องไม่ต้องพึ่งพาสิทธิ์ของผู้ใช้ในการสัมผัสฐานข้อมูลนั่นคือสิ่งที่บัญชีบริการมีไว้สำหรับและการรักษาความปลอดภัยระดับบริการควรใช้ได้ทั่วทั้งฐานข้อมูลวิธีนี้ DBA จึงไม่ต้องเสียเวลาและเงินในการปรับแต่งความปลอดภัย แต่ละ sprocs
Shaun Wilson

2
ฉันจะไม่มีนักพัฒนาทิ้ง / สร้าง sprocs ที่เป็นของผลิตภัณฑ์เชิงพาณิชย์ ลองคิดดูสิฉันคงไม่มี DBA ทำแบบนั้นเหมือนกัน ฉันเห็นสิ่งที่คุณกำลังได้รับกล่าวคือ "จะเกิดอะไรขึ้นถ้า DBA จำเป็นต้องปรับแต่งการรักษาความปลอดภัยใน sproc หลังการปรับใช้สำหรับผลิตภัณฑ์เชิงพาณิชย์" ฉันขอย้ำว่าระบบที่นำไปใช้อย่างถูกต้องไม่ต้องอาศัยสิทธิ์ของผู้ใช้และควรใช้การรักษาความปลอดภัยระดับบริการทั่วทั้งฐานข้อมูล ฉันได้ทำงานกับ DBA ที่จะติดตั้งลงในระบบสาธิต / เริ่มต้นจากนั้นทำการเปรียบเทียบสคีมาเพื่อให้แน่ใจว่าการอัปเกรดนั้นปลอดภัย IMO นี่คือสิ่งที่พวกเขาว่าจ้างให้ทำ
Shaun Wilson

31

หากคุณกำลังจัดการกับโพรซีเดอร์ที่จัดเก็บไว้เท่านั้นสิ่งที่ง่ายที่สุดที่ควรทำคืออาจจะวาง proc แล้วสร้างใหม่ คุณสามารถสร้างโค้ดทั้งหมดเพื่อทำสิ่งนี้โดยใช้วิซาร์ดสร้างสคริปต์ใน SQL Server

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[YourSproc]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[YourSproc]

CREATE PROCEDURE YourSproc...

20

จากSQL Server 2016 CTP3คุณสามารถใช้ คำสั่งDIEใหม่แทนการIFห่อใหญ่

ไวยากรณ์:

วาง {PROC | ขั้นตอน} [IF EXISTS] {[schema_name. ] ขั้นตอน} [, ... n]

ค้นหา:

DROP PROCEDURE IF EXISTS usp_name

ข้อมูลเพิ่มเติมที่นี่



4

นอกเหนือจากสิ่งที่ได้กล่าวไปแล้วฉันยังต้องการเพิ่มแนวทางที่แตกต่างและสนับสนุนการใช้กลยุทธ์การปรับใช้สคริปต์ที่แตกต่างกัน แทนการทำสคริปต์ stateful ที่ตรวจสอบเสมอสถานะปัจจุบันและการกระทำบนพื้นฐานของรัฐที่ปรับใช้ผ่านชุดของสคริปต์ไร้สัญชาติที่อัพเกรดจากรุ่นที่รู้จักกันดี ฉันได้ใช้กลยุทธ์นี้และได้ผลดีเนื่องจากสคริปต์การปรับใช้ของฉันตอนนี้ "IF" ทั้งหมดฟรี


! ที่น่าสนใจ ในช่วงห้าปีที่คุณโพสต์คำตอบนี้มีการพัฒนาเพิ่มเติมในวิธีการควบคุมเวอร์ชันฐานข้อมูลของคุณหรือไม่
Thomas L Holaday

4

คุณสามารถเขียนแบบสอบถามได้ดังนี้:

IF OBJECT_ID('ProcedureName','P') IS NOT NULL
    DROP PROC ProcedureName
GO

CREATE PROCEDURE [dbo].[ProcedureName]
...your query here....

เพื่อให้มีความเฉพาะเจาะจงมากขึ้นในไวยากรณ์ด้านบน:
OBJECT_IDเป็นหมายเลข ID เฉพาะสำหรับอ็อบเจ็กต์ภายในฐานข้อมูลซึ่ง SQL Server จะใช้ภายใน เนื่องจากเรากำลังส่งProcedureNameตามด้วยคุณ object type Pซึ่งบอก SQL Server ว่าคุณควรหาวัตถุที่เรียกว่าProcedureNameซึ่งเป็นโพรซีเดอร์ประเภทคือ P

แบบสอบถามนี้จะค้นหาโพรซีเดอร์และหากมีก็จะทิ้งและสร้างใหม่

สำหรับข้อมูลโดยละเอียดเกี่ยวกับ OBJECT_ID และประเภท Object โปรดไปที่: SYS.Objects



0

ฉันมี proc ที่จัดเก็บไว้ซึ่งช่วยให้ลูกค้าสามารถขยายการตรวจสอบความถูกต้องได้หากมีอยู่ฉันไม่ต้องการเปลี่ยนแปลงหากไม่ต้องการสร้างวิธีที่ดีที่สุดที่ฉันพบ:

IF OBJECT_ID('ValidateRequestPost') IS NULL
BEGIN
    EXEC ('CREATE PROCEDURE ValidateRequestPost 
    @RequestNo VARCHAR(30),
    @ErrorStates VARCHAR(255) OUTPUT
AS
BEGIN
    SELECT @ErrorStates = @ErrorStates
END')
END

2
ฉันไม่ได้ให้การลงคะแนน แต่เดาฉันจะบอกว่ามันถูกลงคะแนนเนื่องจากโซลูชันนี้นำเสนอความซับซ้อนใหม่ ๆ ด้วยการหลีกเลี่ยงอักขระเครื่องหมายคำพูดภายในเนื้อหาของขั้นตอนที่จัดเก็บ
donperk

0

รหัสด้านล่างจะตรวจสอบว่ามีขั้นตอนการจัดเก็บอยู่แล้วหรือไม่

หากมีอยู่จะมีการเปลี่ยนแปลงหากไม่มีอยู่ระบบจะสร้างกระบวนงานที่จัดเก็บใหม่ให้คุณ:

//syntax for Create and Alter Proc 
DECLARE @Create NVARCHAR(200) = 'Create PROCEDURE sp_cp_test'; 
DECLARE @Alter NVARCHAR(200) ='Alter PROCEDURE sp_cp_test'; 
//Actual Procedure 
DECLARE @Proc NVARCHAR(200)= ' AS BEGIN select ''sh'' END'; 
//Checking For Sp
IF EXISTS (SELECT * 
           FROM   sysobjects 
           WHERE  id = Object_id('[dbo].[sp_cp_test]') 
                  AND Objectproperty(id, 'IsProcedure') = 1 
                  AND xtype = 'p' 
                  AND NAME = 'sp_cp_test') 
  BEGIN 
      SET @Proc=@Alter + @Proc 

      EXEC (@proc) 
  END 
ELSE 
  BEGIN 
      SET @Proc=@Create + @Proc 

      EXEC (@proc) 
  END 

go 

0

ตัวเลือกที่ดีกว่าอาจใช้เครื่องมือเช่น Red-Gate SQL Compare หรือ SQL Examiner เพื่อเปรียบเทียบความแตกต่างโดยอัตโนมัติและสร้างสคริปต์การย้ายข้อมูล

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