【问题标题】:sys.types returns wrong data typesys.types 返回错误的数据类型
【发布时间】: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 上工作了一半,它返回的数据类型如 NamePhone 不是该列的实际数据类型:

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.COLUMNSsys.* 表,这不是最佳做法。

为什么某些数据类型以NamePhone 为前缀?

如何为每一列定位正确的数据类型?

【问题讨论】:

  • 看起来您正在使用“用户定义的数据类型”,这是您要返回的数据类型。在我看来,这将是正确的行为。
  • 我希望你永远不需要改变那些数据类型;恐怕你会进入一个受伤的世界。
  • @DaleK,我没有硬编码的PhoneName,正在从sys.types 获取。但是我在sys.types 中看不到任何其他可以返回我nvarchar(50) 的列,所以如果我不从sys.types 获取该数据类型,我应该从哪里获取它?

标签: sql-server tsql types data-masking dynamic-data-masking


【解决方案1】:

如果你希望查询返回系统数据类型nvarchar(50)(而不是用户定义的数据类型Name),你应该用sys.types这样改变JOIN:

JOIN sys.types tp ON tp.user_type_id = mc.system_type_id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-12
    • 2012-03-28
    • 1970-01-01
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 2015-11-17
    相关资源
    最近更新 更多