【发布时间】:2021-11-29 22:43:54
【问题描述】:
我的目标是编写脚本并导出 Dynamic Data Masking。
为此,我创建了一个允许我动态创建代码的查询:
SELECT
schema_name(tbl.schema_id) AS schema_name,
tbl.name as table_name,
mc.name AS column_name,
mc.is_masked
, [Type] =
CASE
WHEN tp.[name] IN ('varchar', 'char') THEN tp.[name] + '(' + IIF(mc.max_length = -1, 'max', CAST(mc.max_length AS VARCHAR(25))) + ')'
WHEN tp.[name] IN ('nvarchar','nchar') THEN tp.[name] + '(' + IIF(mc.max_length = -1, 'max', CAST(mc.max_length / 2 AS VARCHAR(25)))+ ')'
WHEN tp.[name] IN ('decimal', 'numeric') THEN tp.[name] + '(' + CAST(mc.[precision] AS VARCHAR(25)) + ', ' + CAST(mc.[scale] AS VARCHAR(25)) + ')'
WHEN tp.[name] IN ('datetime2') THEN tp.[name] + '(' + CAST(mc.[scale] AS VARCHAR(25)) + ')'
ELSE tp.[name]
END,
mc.masking_function
,'ALTER TABLE '
+ schema_name(tbl.schema_id) + '.' + tbl.name +
' ALTER COLUMN '
+ mc.name + ' ' +
CASE
WHEN tp.[name] IN ('varchar', 'char') THEN tp.[name] + '(' + IIF(mc.max_length = -1, 'max', CAST(mc.max_length AS VARCHAR(25))) + ')'
WHEN tp.[name] IN ('nvarchar','nchar') THEN tp.[name] + '(' + IIF(mc.max_length = -1, 'max', CAST(mc.max_length / 2 AS VARCHAR(25)))+ ')'
WHEN tp.[name] IN ('decimal', 'numeric') THEN tp.[name] + '(' + CAST(mc.[precision] AS VARCHAR(25)) + ', ' + CAST(mc.[scale] AS VARCHAR(25)) + ')'
WHEN tp.[name] IN ('datetime2') THEN tp.[name] + '(' + CAST(mc.[scale] AS VARCHAR(25)) + ')'
ELSE tp.[name]
END
+ ' MASKED WITH (FUNCTION = '''
-- + mc.masking_function
+ CAST(mc.masking_function COLLATE Latin1_General_CI_AI AS nvarchar(100))
+ ''');'
FROM sys.masked_columns AS mc
JOIN sys.tables AS tbl ON mc.[object_id] = tbl.[object_id]
JOIN sys.types tp ON mc.user_type_id = tp.user_type_id
WHERE mc.is_masked = 1;
问题在于,这段代码在 AdventureWorks 上工作了一半,它返回的数据类型如 Name 或 Phone 不是该列的实际数据类型:
| schema_name | table_name | column_name | is_masked | Type | masking_function | (No column name) |
|---|---|---|---|---|---|---|
| Person | Person | FirstName | 1 | Name | partial(2, "xxxx", 0) | ALTER TABLE Person.Person ALTER COLUMN FirstName Name MASKED WITH (FUNCTION = 'partial(2, "xxxx", 0)'); |
| Person | Person | LastName | 1 | nvarchar(50) | default() | ALTER TABLE Person.Person ALTER COLUMN LastName nvarchar(50) MASKED WITH (FUNCTION = 'default()'); |
| Person | PersonPhone | PhoneNumber | 1 | Phone | partial(5, "XXXXXXX", 0) | ALTER TABLE Person.PersonPhone ALTER COLUMN PhoneNumber Phone MASKED WITH (FUNCTION = 'partial(5, "XXXXXXX", 0)'); |
| Person | EmailAddress | EmailAddress | 1 | nvarchar(50) | email() | ALTER TABLE Person.EmailAddress ALTER COLUMN EmailAddress nvarchar(50) MASKED WITH (FUNCTION = 'email()'); |
我有一个查询是 working nicely,但它正在加入 INFORMATION_SCHEMA.COLUMNS 和 sys.* 表,这不是最佳做法。
为什么某些数据类型以Name 或Phone 为前缀?
如何为每一列定位正确的数据类型?
【问题讨论】:
-
看起来您正在使用“用户定义的数据类型”,这是您要返回的数据类型。在我看来,这将是正确的行为。
-
我希望你永远不需要改变那些数据类型;恐怕你会进入一个受伤的世界。
-
@DaleK,我没有硬编码的
Phone或Name,正在从sys.types获取。但是我在sys.types中看不到任何其他可以返回我nvarchar(50)的列,所以如果我不从sys.types获取该数据类型,我应该从哪里获取它?
标签: sql-server tsql types data-masking dynamic-data-masking