關於SQL腳本編寫建議


最近在做安裝包的時候編寫sql腳本自動生成庫,發現沒有在寫sql腳本沒有一定的規范,寫出來的腳本可能會害了同事和自己,所以總結了以下內容,以供參考。

1、創建表的腳本范例
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DIMRoles]') AND xtype = 'U')

BEGIN

CREATE TABLE [DIMRoles](

[Key] [int] NOT NULL,

[Name] [nvarchar](256) NOT NULL,

PRIMARY KEY CLUSTERED

(

[Key] ASC

) ON [PRIMARY],

UNIQUE NONCLUSTERED

(

[Name] ASC

) ON [PRIMARY]

) ON [PRIMARY]

END



注意事項:

A、一定要先判斷表是否存在,不存在才創建,而不能存在刪除原表進行新表創建,重復執行會導致客戶數據丟失!

2、修改表范例
2.1增加字段,增加控制(索引,不能為空等等)
IF NOT exists(select * from syscolumns where id=object_id('DIMUsers') and name='Phone')

BEGIN

ALTER TABLE dbo.DIMUsers ADD Phone NVARCHAR(20) NOT NULL DEFAULT('')

END



注意事項:

A、一定要判斷字段是否存在表,不存在才創建。

B、一定看清楚判斷的字段和表是否一樣,不要上面判斷A表,下面修改B表。

2.2修改刪除字段
修改:

IF exists(select * from syscolumns where id=object_id('DIMUsers') and name='Phone')

BEGIN

ALTER TABLE dbo.DIMUsers ALTER COLUMN Phone NVARCHAR(50)

END

刪除:

IF exists(select * from syscolumns where id=object_id('DIMUsers') and name='Phone')

BEGIN

ALTER TABLE dbo.DIMUsers DROP COLUMN Phone

END



注意事項:

A、一定要判斷表的字段存在,不存在的話不存在修改和刪除的意義。



3、初始化表數據范例
注意事項:

1、切勿使用delete 你要插入的表沒有加上條件。

2、如果自增長字段最好關閉自增長,然后刪除先插入你要加入到這張表的數據,因為這個ID是固定的。

SET IDENTITY_INSERT DIMUsers ON

DELETE FROM DIMUsers WHERE [Key] IN(1,2,3,4);

INSERT INTO DIMUsers ([Key], [Name], Password, Type, Nickname, UpperName, RegisterTime)

values (1, N'sa', N'123', 0, N'系統管理員', N'SA', getdate());

INSERT INTO DIMUsers ([Key], [Name], Password, Type, Nickname, UpperName, RegisterTime)

values (2, N'administrator', N'', 0, N'系統管理員', N'ADMINISTRATOR', getdate());

INSERT INTO DIMUsers ([Key], [Name], Password, Type, Nickname, UpperName, RegisterTime)

values (3, N'admin', N'123', 0, N'系統管理員', N'ADMIN', getdate());

INSERT INTO DIMUsers ([Key], [Name], Password, Type, Nickname, UpperName, RegisterTime)

values (4, N'public', N'', 1, N'公共聊天室', N'PUBLIC', getdate());

SET IDENTITY_INSERT DIMUsers OFF

如果系統的主鍵不是自增長的最好辦了,上面的例子是最難辦的自增長例子。

4、修改函數、存儲過程、視圖、索引
注意事項:

A、因為這些東西重復更新的話可以刪除原來的保證最新的就可以,所以只需要判斷是否存在即可。

函數示例:

IF OBJECT_ID('FUN_GetChildList') IS NOT NULL

DROP FUNCTION FUN_GetChildList

GO

/****** 對象: UserDefinedFunction [dbo].[FUN_GetChildList] 腳本日期: 07/05/2011 09:40:16 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

/*

author:wenjl

createtime:2011-4-29

desc:--用途 根據傳遞的參數獲取所有子節點

--取法舉例SELECT * FROM FUN_GetChildList('COMPANY','TQ00000100')

*/

CREATE FUNCTION [dbo].[FUN_GetChildList] (

@Table Nvarchar(100),

@Value Nvarchar(100)

)



RETURNS @tResult TABLE (

-- 定義結果表

RESULT Nvarchar(100)

)



AS

BEGIN

-- 子類型表、父類型表、子類型數

DECLARE @tChild TABLE(RESULT Nvarchar(100))

DECLARE @tFather TABLE(RESULT Nvarchar(100))

DECLARE @Count SmallInt



-- 預先置傳入的值到@tFather中

INSERT INTO @tFather

VALUES (@Value)



WHILE 1 = 1

BEGIN

-- 循環中,先將@tFather中內容放到@tResult中;

INSERT INTO @tResult SELECT RESULT FROM @tFather



-- 將@tChild清空,再取@tFather的所有子類型到@tChild中;

DELETE FROM @tChild



-- 根據不同的表追加寫到IF內部的語句

---------------------------------------------------------------------------------------

IF @Table ='DIMDEPT'

BEGIN

INSERT INTO @tChild

SELECT RESULT = did

FROM DIMDEPT

WHERE pdid IN (SELECT RESULT FROM @tFather)

END

---------------------------------------------------------------------------------------

-- 當@tChild空時,退出;

SELECT @Count = COUNT(*) FROM @tChild

IF @Count = 0

BREAK



-- 將@tFather清空,並將@tChild中內容給@tFather。

DELETE FROM @tFather

INSERT INTO @tFather SELECT RESULT FROM @tChild

END

RETURN

END



存儲過程示例:

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DIMAddFriend]') AND OBJECTPROPERTY(id,N'IsProcedure') = 1)

DROP PROC DIMAddFriend

GO

create proc [dbo].[DIMAddFriend](@user nvarchar(256), @friend nvarchar(256))

as

begin

insert into DIMUserRelationship (HostKey,GuestKey,Relationship,RenewTime)

select host.[Key] as HostKey,guest.[Key] as GuestKey,0,getdate()

from DIMUsers host,DIMUsers guest

where

(host.UpperName=upper(@user) or host.UpperName=upper(@friend)) and

(guest.UpperName=upper(@friend) or guest.UpperName=upper(@user)) and

host.[Key]<>guest.[Key]

end

視圖示例:

由於視圖判斷沒有辦法所以版本統一,所以寫了2個版本。

2005以上版本:

IF EXISTS (SELECT * FROM sys.views WHERE OBJECT_ID=OBJECT_ID(N'VB_AccountPayableDetail') )

DROP VIEW VB_AccountPayableDetail

go



CREATE VIEW VB_AccountPayableDetail

AS

SELECT

A.COMPANY_ID,

A.ACCOUNT_PAYABLE_ID,

A.SNO,

A.MATERIAL_ID,

A.MATERIAL_NO,

A.MATERIAL_NAME,

A.MATERIAL_SPECIFICATION,

A.CURRENCY_ID,

EXCHANGE_RATE = CAST(A.EXCHANGE_RATE AS NUMERIC(18,2)),

A.UNIT_ID,

QUANTITY = CAST(A.QUANTITY AS NUMERIC(18,2)),

UNIT_PRICE = CAST(A.UNIT_PRICE AS NUMERIC(18,2)),

TAX_RATE = CAST(A.TAX_RATE AS NUMERIC(18,2)),

AMOUNT = CAST(A.AMOUNT AS NUMERIC(18,2)),

A.REMARK,

CURRENCY = B.NAME,

UNIT = C.NAME

FROM ACCOUNT_PAYABLE_ITEM A

LEFT JOIN S_CODELIB B

ON A.COMPANY_ID = B.COMPANY_ID

AND A.CURRENCY_ID = B.ID

LEFT JOIN S_CODELIB C

ON A.COMPANY_ID = C.COMPANY_ID

AND A.UNIT_ID = C.ID

2000版本:

IF EXISTS (SELECT * FROM sysviews WHERE OBJECT_ID=OBJECT_ID(N'VB_AccountPayableDetail') )

DROP VIEW VB_AccountPayableDetail

go



CREATE VIEW VB_AccountPayableDetail

AS

SELECT

A.COMPANY_ID,

A.ACCOUNT_PAYABLE_ID,

A.SNO,

A.MATERIAL_ID,

A.MATERIAL_NO,

A.MATERIAL_NAME,

A.MATERIAL_SPECIFICATION,

A.CURRENCY_ID,

EXCHANGE_RATE = CAST(A.EXCHANGE_RATE AS NUMERIC(18,2)),

A.UNIT_ID,

QUANTITY = CAST(A.QUANTITY AS NUMERIC(18,2)),

UNIT_PRICE = CAST(A.UNIT_PRICE AS NUMERIC(18,2)),

TAX_RATE = CAST(A.TAX_RATE AS NUMERIC(18,2)),

AMOUNT = CAST(A.AMOUNT AS NUMERIC(18,2)),

A.REMARK,

CURRENCY = B.NAME,

UNIT = C.NAME

FROM ACCOUNT_PAYABLE_ITEM A

LEFT JOIN S_CODELIB B

ON A.COMPANY_ID = B.COMPANY_ID

AND A.CURRENCY_ID = B.ID

LEFT JOIN S_CODELIB C

ON A.COMPANY_ID = C.COMPANY_ID

AND A.UNIT_ID = C.ID



索引示例:

if NOT exists(select * from sysindexes where name='IX_mis_AskForLeaveSheetFact_001')

BEGIN

CREATE NONCLUSTERED INDEX [IX_mis_AskForLeaveSheetFact_001] ON [dbo].[mis_AskForLeaveSheetFact]

(

[begin_date] ASC,

[begin_time] ASC

)

INCLUDE ( [Fact_leave_id],

[e_id],

[end_date],

[end_time],

[holidayNo]) WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]

END

統計信息示例:

這個沒有2000版本的只有2005版本

IF NOT EXISTS(SELECT NAME FROM sys.stats WHERE name='pms_exam_emp_001')

BEGIN

CREATE STATISTICS [pms_exam_emp_001] ON [dbo].[pms_exam_emp]([p_e_id], [e_type], [e_id])

END



這個統計信息是什么東東,這個玩意是跟索引配合的,在進行數據優化的時候很有用處。



以上腳本都要記住的就如果你要增加、修改、刪除一個表,視圖,函數,存儲過程,索引,字段都必須判斷是否存在。



5、關於腳本上傳到svn的規范
1、文件命名規則:
A、每天建立一個文件夾

B、文件名稱以設計的表名,字段名,函數,存儲過程,日期時間,姓名

示例:doa_deletefield_BOM_alter_201109061105_wenjl.sql

存儲過程名稱+動作+時間+姓名

個人覺得加上時間比較好,這樣可以有效避免存儲過程函數等更改的先后問題。最好可以統一開發庫。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM