programing

SQL Server에서 생성 또는 변경을 위해 무엇을합니까?

nasanasas 2020. 12. 3. 07:59
반응형

SQL Server에서 생성 또는 변경을 위해 무엇을합니까?


연도는 2009이고 SQL Server에는 CREATE OR ALTER / REPLACE가 없습니다. 이것이 내가 대신하는 일입니다.

IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES 
           WHERE ROUTINE_NAME = 'SynchronizeRemoteCatalog' 
             AND ROUTINE_SCHEMA = 'dbo' 
             AND ROUTINE_TYPE = 'PROCEDURE')
 EXEC ('DROP PROCEDURE dbo.SynchronizeRemoteCatalog')

CREATE PROCEDURE dbo.SynchronizeRemoteCatalog
AS BEGIN
    -- body
END

트리거의 경우 독점 시스템보기에 의존해야합니다.

그동안 가장 많이 받아 들여지는 대회입니까?

편집 : n8wrl이 제안했듯이 공식 단어 는이 기능이 높은 우선 순위가 아니라고 제안합니다. 따라서 질문입니다.


이 기사는 SQL Server에서 개체를 삭제할 때 권한을 잃는 것에 대해 설명합니다.

따라서 권한을 유지하는 방법은 다음과 같습니다.

IF OBJECT_ID('spCallSomething') IS NULL
    EXEC('CREATE PROCEDURE spCallSomething AS SET NOCOUNT ON;')
GO

ALTER PROCEDURE spCallSomething ... 
--instead of DROP/CREATE

또한 단지 대체 기능 작동 PROCEDUREFUNCTION위의 코드이다.

이 방법을 고려하는 또 다른 이유는 실패에 대한 내성입니다. DROP이 성공했지만 CREATE가 실패했다고 가정하면 손상된 DB로 끝납니다. ALTER 접근 방식을 사용하면 이전 버전의 객체로 끝납니다.


연도는 2009 년이고 SQL Server에는 CREATE OR ALTER / REPLACE가 없습니다.

올해는 2016 년이며 이제 SQL Server 2016 RTM 및 (2016 SP1에 도입 됨 )에 DIE ( 존재하는 경우 삭제CREATE OR ALTER )가 있습니다.

촬영 Drop If Exists에 필요한 주위에 먼저주의를 그대로 적용이 접근 권한을 다시 적용합니다. 구문 예는 다음과 같습니다.

DROP PROCEDURE IF EXISTS dbo.SynchronizeRemoteCatalog

GO

CREATE PROCEDURE dbo.SynchronizeRemoteCatalog
AS
  BEGIN
      BODY:
  END 

GO

/*TODO: Reapply permissions*/

CREATE OR ALTER권한을 유지합니다. 구문 예는 다음과 같습니다.

 CREATE OR ALTER PROCEDURE dbo.SynchronizeRemoteCatalog
 AS
 BEGIN
   BODY:
 END

해당 MSSQL 타이거 팀 블로그 게시물은 설명

CREATE OR ALTER는 다음과 같은 프로그래밍 가능 개체에서 사용할 수 있습니다.

  • 저장된 절차 (기본적으로 컴파일 된 포함)
  • FUNCTIONS (Transact-SQL, 네이티브 컴파일 포함)
  • 트리거
  • 견해

그러나 다음에서 사용할 수 없습니다.

  • 저장소가 필요한 개체 (테이블, 인덱스 및 인덱싱 된 뷰)
  • CLR 사용자 정의 함수
  • 더 이상 사용되지 않는 프로그래밍 가능 개체 (RULE 및 DEFAULT)
  • 프로그래밍이 불가능한 개체 (예 : CREATE ASSEMBLY, CREATE TABLE 또는 CREATE-SCHEMA) 이러한 개체에서 CREATE 및 ALTER의 구문은 구문 및 사용성 관점과 매우 다릅니다.

개발자 IF EXISTS(...) DROP가 물개를 쓸 때마다 강아지가 뭉칩니다. 데이터베이스에 무엇이 있는지 정확히 알고 있어야하며, 업그레이드 스크립트는 현재 버전의 애플리케이션 스키마 ( Version Control and your Database)를 기반으로 CREATe 또는 ALTER를 적절하게 수행해야합니다 .


원격 사이트를 업데이트해야하는 상황이 발생했지만 DROP 권한이 없습니다. 지금까지 SSMS 2008 R2에 내장 된 'DROP and CREATE'스크립트를 사용해 왔지만 지금은 변경해야합니다. 저장 프로 시저 또는 함수를 업데이트해야 할 때 적절한 ALTER 스크립트 위에 드롭하는 세 가지 템플릿을 만들었습니다.

—- Stored Procedure
IF OBJECT_ID('[dbo].[<Name_Of_Routine, , >]') IS NULL
EXEC('CREATE PROCEDURE [dbo].[<Name_Of_Routine, , >] AS SET NOCOUNT ON;')
EXEC('GRANT EXECUTE ON [<Name_Of_Routine, , >] TO Public AS dbo;')
GO

—- Scalar Function
IF OBJECT_ID('[dbo].[<Name_Of_Routine, , >]') IS NULL
EXEC('CREATE FUNCTION [dbo].[<Name_Of_Routine, , >] (@i INT) RETURNS INT AS BEGIN RETURN 0 END;')
EXEC('GRANT EXECUTE ON [<Name_Of_Routine, , >] TO Public AS dbo;')
GO

—- Table-based Function
IF OBJECT_ID('[dbo].[<Name_Of_Routine, , >]') IS NULL
EXEC('CREATE FUNCTION [dbo].[<Name_Of_Routine, , >] (@i INT) RETURNS @O TABLE(i INT) AS BEGIN INSERT INTO @O SELECT 0 RETURN END;')
GO

모든 특수 권한은 각 CREATE 후에 스크립팅됩니다 (테이블 함수에 권한을 할당 할 수 없음). 그 후에 ALTER는 변경하지 않으며 권한을 추가하거나 수정해도 그대로 유지됩니다. 이렇게하면 함수 또는 저장 프로 시저의 이름을 복사하고 템플릿 매개 변수 대체를 사용하여 이러한 스크립틀릿의 완성을 자동화하는 것은 쉬운 작업입니다.

이제 저는 Microsoft의 좋은 사람들이 이것을“Script ___ as”목록에 추가하거나이 스크립팅이 '베이킹'되도록 우리 자신을 만들 수있는 기능을 제공하기를 바랍니다.

https://connect.microsoft.com/SQLServer/feedback/details/344991/create-or-alter-statement 에서 SQL Server 피드백 항목 뒤에 약간의 가중치를 부여 할 수 있습니다 . 아직 공개적으로 접근 할 수있는 몇 안되는 것으로 보이며 "가까운 장래에이 제품을 출시 할 수 있는지 결정하기 위해 타당성 검토를 시작했습니다"라고 말합니다. 목소리가 많을수록 이런 일이 발생할 가능성이 높아집니다!

(업데이트 : 이제 트리거 및 뷰에 대해 다음 코드도 사용)

-- Triggers
IF OBJECT_ID('[dbo].[<Name_Of_Trigger, , >]') IS NULL -- Check if Trigger Exists
    EXEC('CREATE TRIGGER [dbo].[<Name_Of_Trigger, , >] ON [<Name_Of_Table, , >] AFTER UPDATE AS SET NOCOUNT ON;') -- Create dummy/empty SP
GO

-- Views
IF OBJECT_ID('[dbo].[<Name_Of_View, , >]') IS NULL -- Check if View Exists
    EXEC('CREATE VIEW [dbo].[<Name_Of_View, , >] AS SELECT 1;') -- Create dummy/empty View
GO

나는 OBJECT_ID(...) IS NOT NULLDROP 전에 사용할 것 입니다.

개체 식별자는 고유해야하므로 시스템 테이블을 사용하지 않고 작동합니다.

CREATE TRIGGER dbo.ExistingTable ON dbo.AnotherTable FOR UPDATE
AS 
SET NOCOUNT ON
GO

준다

Msg 2714, Level 16, State 2, Procedure MetaClass, Line 3
There is already an object named ExistingTable ' in the database.

나는 일반적으로 소스 제어 등으로 작업하는 방식 때문에 ALTER를 사용합니다.


그것은 기본적으로 그것을하는 방법입니다. "EXEC"접근 방식을 사용하는 특별한 이유가 있는지 궁금합니다.

IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = 'SynchronizeRemoteCatalog' AND ROUTINE_SCHEMA = 'dbo' AND ROUTINE_TYPE = 'PROCEDURE')
    EXEC ('DROP PROCEDURE dbo.SynchronizeRemoteCatalog')

왜 안 되는가 :

IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = 'SynchronizeRemoteCatalog' AND ROUTINE_SCHEMA = 'dbo' AND ROUTINE_TYPE = 'PROCEDURE')
    DROP PROCEDURE dbo.SynchronizeRemoteCatalog

???

트리거의 경우 sys.triggers. 그것들은 "sys"스키마의 시스템 카탈로그 뷰입니다. 실제로는 엄격하게 또는 직접적으로 테이블이 아닙니다.

마크


altera drop는 정말 나쁜 습관이고, 객체가 생성 (24/7 db!)에 실패하면 DB를 나쁜 상태로 남겨 둘 수 있고 다른 포스터가 nuking 권한에 대해 언급 한 내용도 있기 때문에 항상 내 객체 를 사용합니다.

Sublime, Atom 및 VS Code와 같은 편집기를 사용하면 코드 조각을 템플릿으로 만들어 골격 스크립트를 빠르게 생성 할 수 있습니다. SQL 2016은 이제 마침내 DROP IF EXISTS구조를 지원 하지만 여전히 잘못된 방향에서 접근합니다. 모든 것이 먼 과거와 그 이후 drop/create의 한 번 이 아니라는 것입니다 . 또한, 난보다 애호가를하지 않도록, 가능한 된 작업이 짧게 내 헤더를 만들기 위해 노력했다 는 AS 스텁.createaltercreate proc dbo.myproc ascreate

견해:

if objectproperty(object_id('dbo.myview'), 'IsView') is null begin
    exec('create view dbo.myview as select 1 c')
end
go
alter view dbo.myview as
    -- select *
    -- from table
go

프록 :

if objectproperty(object_id('dbo.myproc'), 'IsProcedure') is null begin
    exec('create proc dbo.myproc as')
end
go
alter procedure dbo.myproc as
    set nocount on
    -- Add the stored proc contents here...
go

UDF (스칼라) :

if objectproperty(object_id('dbo.myudf'), 'IsScalarFunction') is null begin
    exec('create function dbo.myudf returns int as begin return null end')
end
go
alter function dbo.myudf(@s varchar(100)) returns int as
begin
    -- return len(@s)
end
go

UDF (테이블 형식) :

if objectproperty(object_id('dbo.myudf'), 'IsTableFunction') is null begin
    exec('create function dbo.myudf returns @t table(x int) as begin return end')
end
go
alter function dbo.myudf(@s varchar(100))
    returns @result table (
        -- Columns returned by the function
        id int identity(1, 1) primary key not null
        ,result varchar(100) null
    )
begin
    return
end
go

잠시 꺼진 것 같습니다 : 링크 텍스트

나를위한 전형적인 스크립트 :

IF EXISTS (SELECT name FROM sysobjects WHERE name = 'ig_InsertDealer' AND type = 'P')
    DROP PROC dbo.ig_InsertDealer
GO 
CREATE PROCEDURE dbo.ig_InsertDealer
...
GO
GRANT EXECUTE ON dbo.ig_InsertDealer TO ...
GO

컨텍스트에 따라 사용합니다. 초기 빌드 또는 주요 리팩토링 스크립트는 check / drop / create를 사용하고 순수 유지 관리 스크립트는 alter를 사용합니다.


두 가지 이유로 CREATE-ALTER접근 방식 (구문이 아님)을 선호합니다 DROP-CREATE.

  • 권한 ( DROP-CREATE다시 만들어야 함)
  • object_id (개체를 변경해도 변경되지 않음)

DROP-CREATE:

--Initial creation:
CREATE PROCEDURE dbo.my_proc
AS
SELECT *
FROM dbo.a
WHERE i < 10;
GO

SELECT OBJECT_ID('dbo.my_proc');
GO


-- Recreating
DROP PROCEDURE IF EXISTS dbo.my_proc;
GO

CREATE PROCEDURE dbo.my_proc
AS
-- some meaningless comment
SELECT *
FROM dbo.a
WHERE i < 10;
GO

SELECT OBJECT_ID('dbo.my_proc');
GO

DB 바이올린

우리가 볼 수 있듯이 object_id변경되었습니다.

예 2 : CREATE-ALTER

-- Initial creation
CREATE PROCEDURE dbo.my_proc2
AS
SELECT *
FROM dbo.a
WHERE i < 10;
GO

SELECT OBJECT_ID('dbo.my_proc2');
GO

-- Altering
CREATE OR ALTER PROCEDURE dbo.my_proc2
AS
-- some meaningless comment
SELECT *
FROM dbo.a
WHERE i < 10;
GO

SELECT OBJECT_ID('dbo.my_proc2');
GO

DB 바이올린

이 시나리오에서는 object_id동일하게 유지됩니다.


이로 인해 몇 가지 문제가 발생할 수있는 샘플 시나리오입니다. SQL Server 2016 쿼리 저장소를 사용하고 저장 프로 시저에 대해 특정 쿼리 계획을 강제로 사용한다고 가정 해 보겠습니다.

드롭 생성

USE T1;
GO
-- make sure that Query Store is READ_WRITE 
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[a]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[a](
    [i] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [g] [uniqueidentifier] NULL,
    [z] VARCHAR(10)
);
END
GO

-- populate table (15k records)
INSERT INTO dbo.a(g, z)
SELECT NEWID(), number
FROM (SELECT CAST([key] AS INT) AS number 
    FROM OPENJSON( '[1' + REPLICATE(',1',3000-1)+']')
    ) AS num
GO 5

-- initial creation
CREATE PROCEDURE dbo.my_proc
AS
SELECT *
FROM dbo.a
WHERE z LIKE '12%'
AND 1 = (SELECT 1);
GO

-- Clustered Index Scan
EXEC dbo.my_proc;

EXEC sp_query_store_flush_db; 

SELECT qsq.query_id,
    qsq.query_text_id,
    qsq.context_settings_id,
    qsq.[object_id],
    OBJECT_NAME(qsq.[object_id]) AS [object_name],
    qsp.is_forced_plan,
    qsqt.query_sql_text,
    qsrs.count_executions,
    CAST(qsp.query_plan AS XML) AS sql_query_plan
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt
ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp
ON qsq.query_id= qsp.query_id
JOIN sys.query_store_runtime_stats qsrs
ON qsrs.plan_id = qsp.plan_id
WHERE query_sql_text LIKE '%dbo.a%'
AND qsq.[object_id] <> 0
ORDER BY qsq.query_id;
GO
--dc1

-- creating index
CREATE NONCLUSTERED INDEX IX_dbo_a_z
ON dbo.a([z] ASC) INCLUDE ([i], [g]);
GO

-- index seek
EXEC dbo.my_proc;

EXEC sp_query_store_flush_db; 

SELECT qsq.query_id,
    qsq.query_text_id,
    qsq.context_settings_id,
    qsq.[object_id],
    OBJECT_NAME(qsq.[object_id]) AS [object_name],
    qsp.is_forced_plan,
    qsqt.query_sql_text,
    qsrs.count_executions,
    CAST(qsp.query_plan AS XML) AS sql_query_plan
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt
ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp
ON qsq.query_id= qsp.query_id
JOIN sys.query_store_runtime_stats qsrs
ON qsrs.plan_id = qsp.plan_id
WHERE query_sql_text LIKE '%dbo.a%'
AND qsq.[object_id] <> 0
ORDER BY qsq.query_id;

-- forcing plan GUI, clustered scan
-- dc3

EXEC sp_query_store_flush_db; 
SELECT qsq.query_id,
    qsq.query_text_id,
    qsq.context_settings_id,
    qsq.[object_id],
    OBJECT_NAME(qsq.[object_id]) AS [object_name],
    qsp.is_forced_plan,
    qsqt.query_sql_text,
    qsrs.count_executions,
    CAST(qsp.query_plan AS XML) AS sql_query_plan
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt
ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp
ON qsq.query_id= qsp.query_id
JOIN sys.query_store_runtime_stats qsrs
ON qsrs.plan_id = qsp.plan_id
WHERE query_sql_text LIKE '%dbo.a%'
AND qsq.[object_id] <> 0
ORDER BY qsq.query_id;
-- dc4

-- Clustered Index Scan
EXEC dbo.my_proc;

EXEC sp_query_store_flush_db; 
SELECT qsq.query_id,
    qsq.query_text_id,
    qsq.context_settings_id,
    qsq.[object_id],
    OBJECT_NAME(qsq.[object_id]) AS [object_name],
    qsp.is_forced_plan,
    qsqt.query_sql_text,
    qsrs.count_executions,
    CAST(qsp.query_plan AS XML) AS sql_query_plan
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt
ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp
ON qsq.query_id= qsp.query_id
JOIN sys.query_store_runtime_stats qsrs
ON qsrs.plan_id = qsp.plan_id
WHERE query_sql_text LIKE '%dbo.a%'
AND qsq.[object_id] <> 0
ORDER BY qsq.query_id;
-- dc5

/* MAIN PART  - DROP - RECREATE */
DROP PROCEDURE IF EXISTS dbo.my_proc;
GO

CREATE PROCEDURE dbo.my_proc
AS
-- some meaningless comment added by developer
SELECT *
FROM dbo.a
WHERE z LIKE '12%'
AND 1 = (SELECT 1);
GO

/* MAIN PART END */

-- Index Seek
EXEC dbo.my_proc;

EXEC sp_query_store_flush_db; 
SELECT qsq.query_id,
    qsq.query_text_id,
    qsq.context_settings_id,
    qsq.[object_id],
    OBJECT_NAME(qsq.[object_id]) AS [object_name],
    qsp.is_forced_plan,
    qsqt.query_sql_text,
    qsrs.count_executions,
    CAST(qsp.query_plan AS XML) AS sql_query_plan
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt
ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp
ON qsq.query_id= qsp.query_id
JOIN sys.query_store_runtime_stats qsrs
ON qsrs.plan_id = qsp.plan_id
WHERE query_sql_text LIKE '%dbo.a%'
AND qsq.[object_id] <> 0
ORDER BY qsq.query_id;
-- object_id in query store is NULL
-- is_forced_plan flag is ignored !!!  

첫 실행 :
DC1

색인 추가 및 실행 : 여기에 이미지 설명 입력

강제 계획 : 여기에 이미지 설명 입력 여기에 이미지 설명 입력

또 다른 실행 : 여기에 이미지 설명 입력

이후 DROP-CREATE:여기에 이미지 설명 입력


만들기-변경

USE T2;
GO
-- make sure that Query Store is READ_WRITE 
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[a]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[a](
    [i] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [g] [uniqueidentifier] NULL,
    [z] VARCHAR(10)
);
END
GO

-- populate table (15k records)
INSERT INTO dbo.a(g, z)
SELECT NEWID(), number
FROM (SELECT CAST([key] AS INT) AS number 
    FROM OPENJSON( '[1' + REPLICATE(',1',3000-1)+']')
    ) AS num
GO 5

-- initial creation
CREATE PROCEDURE dbo.my_proc
AS
SELECT *
FROM dbo.a
WHERE z LIKE '12%'
AND 1 = (SELECT 1);
GO

-- Clustered Index Scan
EXEC dbo.my_proc;

EXEC sp_query_store_flush_db; 
SELECT qsq.query_id,
    qsq.query_text_id,
    qsq.context_settings_id,
    qsq.[object_id],
    OBJECT_NAME(qsq.[object_id]) AS [object_name],
    qsp.is_forced_plan,
    qsqt.query_sql_text,
    qsrs.count_executions,
    CAST(qsp.query_plan AS XML) AS sql_query_plan
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt
ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp
ON qsq.query_id= qsp.query_id
JOIN sys.query_store_runtime_stats qsrs
ON qsrs.plan_id = qsp.plan_id
WHERE query_sql_text LIKE '%dbo.a%'
AND qsq.[object_id] <> 0
ORDER BY qsq.query_id;
-- ca1
GO

-- creating index
CREATE NONCLUSTERED INDEX IX_dbo_a_z
ON dbo.a([z] ASC) INCLUDE ([i], [g]);
GO

-- index seek
EXEC dbo.my_proc;

EXEC sp_query_store_flush_db; 
SELECT qsq.query_id,
    qsq.query_text_id,
    qsq.context_settings_id,
    qsq.[object_id],
    OBJECT_NAME(qsq.[object_id]) AS [object_name],
    qsp.is_forced_plan,
    qsqt.query_sql_text,
    qsrs.count_executions,
    CAST(qsp.query_plan AS XML) AS sql_query_plan
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt
ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp
ON qsq.query_id= qsp.query_id
JOIN sys.query_store_runtime_stats qsrs
ON qsrs.plan_id = qsp.plan_id
WHERE query_sql_text LIKE '%dbo.a%'
AND qsq.[object_id] <> 0
ORDER BY qsq.query_id;
--ca2

-- forcing plan GUI
--ca3

EXEC sp_query_store_flush_db; 
SELECT qsq.query_id,
    qsq.query_text_id,
    qsq.context_settings_id,
    qsq.[object_id],
    OBJECT_NAME(qsq.[object_id]) AS [object_name],
    qsp.is_forced_plan,
    qsqt.query_sql_text,
    qsrs.count_executions,
    CAST(qsp.query_plan AS XML) AS sql_query_plan
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt
ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp
ON qsq.query_id= qsp.query_id
JOIN sys.query_store_runtime_stats qsrs
ON qsrs.plan_id = qsp.plan_id
WHERE query_sql_text LIKE '%dbo.a%'
AND qsq.[object_id] <> 0
ORDER BY qsq.query_id;
--ca4

-- Clustered Index Scan
EXEC dbo.my_proc;

EXEC sp_query_store_flush_db; 
SELECT qsq.query_id,
    qsq.query_text_id,
    qsq.context_settings_id,
    qsq.[object_id],
    OBJECT_NAME(qsq.[object_id]) AS [object_name],
    qsp.is_forced_plan,
    qsqt.query_sql_text,
    qsrs.count_executions,
    CAST(qsp.query_plan AS XML) AS sql_query_plan
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt
ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp
ON qsq.query_id= qsp.query_id
JOIN sys.query_store_runtime_stats qsrs
ON qsrs.plan_id = qsp.plan_id
WHERE query_sql_text LIKE '%dbo.a%'
AND qsq.[object_id] <> 0
ORDER BY qsq.query_id;
--ca5
GO

/* MAIN PART  - CREATE-ALTER */
CREATE OR ALTER PROCEDURE dbo.my_proc
AS
-- some meaningless comment added by developer
SELECT *
FROM dbo.a
WHERE z LIKE '12%'
AND 1 = (SELECT 1);
GO

/* MAIN PART END */

-- Clustered Index Scan
EXEC dbo.my_proc;

EXEC sp_query_store_flush_db; 
SELECT qsq.query_id,
    qsq.query_text_id,
    qsq.context_settings_id,
    qsq.[object_id],
    OBJECT_NAME(qsq.[object_id]) AS [object_name],
    qsp.is_forced_plan,
    qsqt.query_sql_text,
    qsrs.count_executions,
    CAST(qsp.query_plan AS XbML) AS sql_query_plan
FROM sys.query_store_query qsq
JOIN sys.query_store_query_text qsqt
ON qsq.query_text_id = qsqt.query_text_id
JOIN sys.query_store_plan qsp
ON qsq.query_id= qsp.query_id
JOIN sys.query_store_runtime_stats qsrs
ON qsrs.plan_id = qsp.plan_id
WHERE query_sql_text LIKE '%dbo.a%'
AND qsq.[object_id] <> 0
ORDER BY qsq.query_id;

-- is_forced_plan is valid

첫 실행 :
여기에 이미지 설명 입력

색인 추가 및 실행 : 여기에 이미지 설명 입력

강제 계획 : 여기에 이미지 설명 입력 여기에 이미지 설명 입력

또 다른 실행 : 여기에 이미지 설명 입력

이후 CREATE-ALTER:여기에 이미지 설명 입력

결과

Drop-Create로 우리는 강제 계획을 잃었습니다.


오류없이 스크립트를 여러 번 실행할 수있는 템플릿이 있습니다.

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[aaa_test]') AND type in (N'P', N'PC'))
    EXEC('CREATE PROCEDURE aaa_test AS')
    EXEC('GRANT EXECUTE ON aaa_test TO someone')
GO

ALTER PROCEDURE aaa_test 
     @PAR1 INT,
     @PAR2 INT=0
AS
BEGIN
    SELECT @PAR1 AS Par1, CASE @PAR2 WHEN 0 THEN 'Default' ELSE 'Other' END AS Par2
END
GO

실행:

EXEC aaa_test 1
EXEC aaa_test 1,5

물체를 떨어 뜨리면 안됩니다. 개체를 삭제하면 두 가지 문제가 있습니다.

1) CREATE가 실패하면 더 이상 객체가 없습니다. (많은 상용구 코드 대신 트랜잭션을 사용하여이를 방지 할 수 있습니다.)

2) 명시 적으로 다시 생성하지 않으면 개체에 대한 권한이 손실됩니다.


"존재하지 않는 경우"조건 내에서 빈 개체를 만든 다음 ALTER를 사용하고 해당 목적을위한 도우미 프로 시저를 작성하는 것을 선호합니다.


올해는 2017 년이고 SQL Server에는 CREATE OR ALTER가 있습니다.

SQL Server 2016 SP1 및 SQL Server vNext에는 다음을위한 새로운 T-SQL 언어 문 – CREATE [OR ALTER] 가 있습니다.

  • 저장 절차
  • 기능
  • 트리거
  • 견해

https://blogs.msdn.microsoft.com/sqlserverstorageengine/2016/11/17/create-or-alter-another-great-language-enhancement-in-sql-server-2016-sp1/


확장 이전 답변 .

내가 접근 방식 CREATE-ALTER보다 선호하는 또 다른 이유 DROP-CREATE. 개체에 대한 특정 속성을 잃을 수 있습니다. ExecIsStartup:

USE master
GO

CREATE TABLE dbo.silly_logging(id INT IDENTITY(1,1) PRIMARY KEY
                               ,created_date DATETIME DEFAULT GETDATE()
                               ,comment VARCHAR(100));
GO

CREATE PROCEDURE dbo.my_procedure 
AS
INSERT INTO dbo.silly_logging(comment)
VALUES ('SQL Server Startup');
GO

-- mark procedure to start at SQL Server instance startup
EXEC sp_procoption @ProcName = 'dbo.my_procedure'
    , @OptionName = 'startup'   
    , @OptionValue = 'on';


SELECT name, create_date, modify_date, is_auto_executed
FROM master.sys.procedures
WHERE is_auto_executed = 1;
--name  create_date modify_date is_auto_executed
--my_procedure  2017-07-28 06:36:21.743 2017-07-28 06:36:24.513 1

이제 누군가 다음을 사용하여이 절차를 업데이트하려고한다고 가정 해 보겠습니다 DROP-CREATE.

DROP PROCEDURE dbo.my_procedure;
GO

CREATE PROCEDURE dbo.my_procedure 
AS
-- adding meaningless comment
INSERT INTO dbo.silly_logging(comment)
VALUES ('SQL Server Startup');
GO

SELECT name, create_date, modify_date, is_auto_executed
FROM master.sys.procedures
WHERE is_auto_executed = 1;
-- empty

그리고 당신이 그것을 모르거나 확인하지 않으면 시작되지 않는 절차로 끝날 것입니다.

참고 URL : https://stackoverflow.com/questions/1434160/what-do-you-do-in-sql-server-to-create-or-alter

반응형