[SQL]使用者自訂類型(User-defined Data Types)

[SQL]使用者自訂類型(User-defined Data Types)

上課有上到,紀錄一下步驟及相關SQL

新增使用者自訂類型步驟

1. 可程式性→類別→新增→使用者定義資料類型

1

2. 設定相關型態,這裡以員工編號(STAFF、nvarchar(6))為例

2

3. 建立完畢可以看到相關定義

3

4. 要看那些欄位為使用者定義資料類型,可以看「檢視相依性」

4

5

相關的SQL


-- 資料來源:德瑞克老師的上課筆記+自行修改
-- sys.types (Transact-SQL)
-- http://technet.microsoft.com/zh-tw/library/ms188021.aspx
-- sys.columns
-- http://msdn.microsoft.com/zh-tw/library/ms176106.aspx
-- 建立使用者定義資料類型別名
-- http://msdn.microsoft.com/zh-tw/library/ms190232.aspx
USE tempdb
GO
-- 建立類型
IF EXISTS
(SELECT name
 FROM
	 sys.types
 WHERE
	 name = 'STAFF') DROP TYPE dbo.STAFF
GO
CREATE TYPE STAFF
FROM nvarchar(6) NOT NULL;
GO

-- 建立測試資料表格
IF  EXISTS
(SELECT *
 FROM
	 sys.objects
 WHERE
	 object_id = object_id(N'[dbo].[EMPLOYEE_USERDATATYPE]')
	 AND type IN (N'U')) DROP TABLE [dbo].[EMPLOYEE_USERDATATYPE]
GO
CREATE TABLE EMPLOYEE_USERDATATYPE
(EMPID STAFF , cData nvarchar(50))
GO

-- 尋找表格中那些欄位定類型為使用者自訂類型
DECLARE @tablename sysname
SET @tablename = N'EMPLOYEE_USERDATATYPE';

SELECT @tablename N'表格名稱'
	 , c.name N'資料行名稱'
	 , t.name N'使用者資料類型'
	 , c.max_length N'資料行的最大長度(Byte)'
	 , d.name N'基本資料型態'
	 , (CASE
		   WHEN d.name = 'nvarchar' AND c.max_length > 0 THEN
			   c.max_length / 2
		   WHEN d.name = 'nchar' AND c.max_length > 0 THEN
			   c.max_length / 2
		   WHEN d.name = 'ntext' AND c.max_length > 0 THEN
			   c.max_length / 2
		   ELSE
			   c.max_length
	   END) N'欄位長度'
FROM
	sys.columns c
	INNER JOIN sys.types t
		ON c.user_type_id = t.user_type_id
	INNER JOIN sys.types d
		ON d.system_type_id = c.system_type_id AND d.system_type_id = d.user_type_id
WHERE
	[object_id] = object_id(@tablename)
	AND t.is_user_defined = 1
GO

-- 查詢那些資料行資料類型是使用者定義資料類型

DECLARE @typename sysname
SET @typename = N'STAFF';
CREATE TABLE #columndef 
(
	[表格名稱] nvarchar(200),
	[資料行名稱] sysname,
	[使用者資料類型] sysname,
	[資料行的最大長度(Byte)] int,
	[基本資料類型] sysname,
	[欄位長度] int	
);

EXEC sp_MSforeachtable ' INSERT INTO #columndef
SELECT ''?'' N''表格名稱'',c.name N''資料行名稱'',
	t.name N''使用者資料類型'',
	c.max_length N''資料行的最大長度(Byte)'',
	d.name N''基本資料類型'',
	(CASE
			WHEN d.name = ''nvarchar'' AND c.max_length > 0 THEN
				c.max_length / 2
			WHEN d.name = ''nchar'' AND c.max_length > 0 THEN
				c.max_length / 2
			WHEN d.name = ''ntext'' AND c.max_length > 0 THEN
				c.max_length / 2
			ELSE
				c.max_length
		END) N''欄位長度''
	
FROM sys.columns c INNER JOIN sys.types t
	ON c.user_type_id = t.user_type_id
	INNER JOIN sys.types d
	ON d.system_type_id= c.system_type_id AND d.system_type_id = d.user_type_id
WHERE [object_id] = object_id(''?'')
and t.is_user_defined = 1';

SELECT *
	 , 'ALTER TABLE ' + [表格名稱] + ' ALTER COLUMN ' + [資料行名稱] + ' ' + [基本資料類型] + 
	 '(' + cast([欄位長度] AS VARCHAR) + ')' N'還原基本型態指令'
	 , 'ALTER TABLE ' + [表格名稱] + ' ALTER COLUMN ' + [資料行名稱] + ' ' + [使用者資料類型] 
	 N'設定使用者資料類型指令'
FROM
	#columndef
WHERE
	[使用者資料類型] = @typename

DROP TABLE #columndef
GO

-- 還原基本型態指令
-- ALTER TABLE [dbo].[EMPLOYEE_USERDATATYPE] ALTER COLUMN EMPID nvarchar(6)
-- 設定使用者資料類型指令
-- ALTER TABLE [dbo].[EMPLOYEE_USERDATATYPE] ALTER COLUMN EMPID STAFF

-- 修改使用者自訂欄位定義
-- 1.修改「資料行(Column)」,改用內建的資料類型
 ALTER TABLE [dbo].[EMPLOYEE_USERDATATYPE] ALTER COLUMN EMPID nvarchar(6)
GO
-- 2.刪除沒有使用的「使用者自訂類型(User-defined Data Types)」
DROP TYPE dbo.STAFF
GO
-- 3.再度建立「使用者自訂類型(User-defined Data Types)」
 CREATE TYPE STAFF
 FROM nvarchar(15) NOT NULL;
GO
-- 4.修改「資料行(Column)」,改用「使用者自訂類型(User-defined Data Types)」
 ALTER TABLE [dbo].[EMPLOYEE_USERDATATYPE] ALTER COLUMN EMPID STAFF
GO

-- 查看變更後的結果
DECLARE @tablename sysname
SET @tablename = N'EMPLOYEE_USERDATATYPE';

SELECT @tablename N'表格名稱'
	 , c.name N'資料行名稱'
	 , t.name N'使用者資料類型'
	 , c.max_length N'資料行的最大長度(Byte)'
	 , d.name N'基本資料型態'
	 , (CASE
		   WHEN d.name = 'nvarchar' AND c.max_length > 0 THEN
			   c.max_length / 2
		   WHEN d.name = 'nchar' AND c.max_length > 0 THEN
			   c.max_length / 2
		   WHEN d.name = 'ntext' AND c.max_length > 0 THEN
			   c.max_length / 2
		   ELSE
			   c.max_length
	   END) N'欄位長度'
FROM
	sys.columns c
	INNER JOIN sys.types t
		ON c.user_type_id = t.user_type_id
	INNER JOIN sys.types d
		ON d.system_type_id = c.system_type_id AND d.system_type_id = d.user_type_id
WHERE
	[object_id] = object_id(@tablename)
	AND t.is_user_defined = 1
GO

-- 還原資料
ALTER TABLE [dbo].[EMPLOYEE_USERDATATYPE] ALTER COLUMN EMPID nvarchar(15)
GO
IF EXISTS
(SELECT name
 FROM
	 sys.types
 WHERE
	 name = 'STAFF') DROP TYPE dbo.STAFF
GO
IF  EXISTS
(SELECT *
 FROM
	 sys.objects
 WHERE
	 object_id = object_id(N'[dbo].[EMPLOYEE_USERDATATYPE]')
	 AND type IN (N'U')) DROP TABLE [dbo].[EMPLOYEE_USERDATATYPE]
GO