为什么(以及如何)使用master..spt_values拆分列?

Gen*_*нин 16 sql t-sql sql-server database-design

将问题的答案分解为"一列拆分为多行",我在此重新编写为[1].

什么是(含义)Type = 'P'以及为什么使用未记录的master..spt_values来拆分列?它有什么好处?


[1]

CREATE TABLE dbo.Table1 
(
    Col1        CHAR(1),
    Col2        CHAR(1),
    Col3        CHAR(1),
    Col4        VARCHAR(50)
)
GO

INSERT INTO dbo.Table1 VALUES ('A','B','C','1,2,3')
GO
INSERT INTO dbo.Table1 VALUES ('D','E','F','6,7,8,9')
GO


SELECT
    T.col1, RIGHT(LEFT(T.col4,Number-1),
    CHARINDEX(',',REVERSE(LEFT(','+T.col4,Number-1))))
FROM
    master..spt_values,
    table1 T
WHERE
    Type = 'P' AND Number BETWEEN 1 AND LEN(T.col4)+1 AND
    (SUBSTRING(T.col4,Number,1) = ','
    -- OR SUBSTRING(T.col4,Number,1)  = '') --this does not work correctly anyway
Run Code Online (Sandbox Code Playgroud)

相关问题:

Per*_*DBA 49

目的

为什么要使用无证件 master..spt-values

Sybase及其私生子MS SQL为产品提供了各种特性和功能,这些特性和功能在系统过程中实现(而不像sqlserver这样的二进制文件,它们是作为服务启动的).这些系统过程程序是用SQL代码编写的,并命名为sp_%. 除了一些秘密内部组件,它们具有与任何其他SQL代码相同的限制和需求.它们是Sybase ASE或SQL Server产品的一部分.因此,他们不需要记录它; 并且内部位不能合理地标记为"未记录".

master..spt_values包含所述系统过程在SQL表中需要的所有各种各样的部分,以产生各种报告.该sp装置的系统程序; spt表示系统程序的表格; 当然values是内容.

查找表

是什么(含义)Type ='P'

人们经常将其描述spt_values为"非规范化",但这是不正确的术语.正确的术语折叠包装.它是26个左右的逻辑查找表,每个表都精美归一化,折叠成一个物理表,带有一Type列来区分逻辑表.

现在在一个普通的数据库中,这将是一个严重错误(只需查看"一个查找表或多个"的答案).但是在服务器目录中,它是可取的,它取代了26个物理表.

  • "L"代表LockType Lookup; "V"代表DeviceType Lookup(V是整个服务器中Device的缩写); 类型"P2"包含按位序数,用于扩展打包到INT的位.

  • 为了执行许多系统过程必须执行的投影,需要以SQL表格形式提供的已知边界内的一组连续数字.类型"P"是0到2047之间的连续数字列表.

  • 这里使用术语投影作为技术上精确的意义,自然逻辑意义,而不是关系代数意义,这是不自然的.

因此,只有一个目的是spt_values,包含26个折叠的,另外分开的参考表和一个投影表.

扩张

普通使用的spt_values话,就像普通的Lookup或Reference或ENUM表一样.首先,查找值:

    SELECT *                    -- list Genders
        FROM Gender 
Run Code Online (Sandbox Code Playgroud)

它的使用方式与Person有一个需要扩展的GenderCode一样(非常扩展,这些怪异的日子):

    SELECT  P.*,                -- list Person
            G.Name              -- expand GenderCode to Name
        FROM Person P
        JOIN Gender G
            ON P.GenderCode = G.GenderCode
Run Code Online (Sandbox Code Playgroud)

例如.sp_lock生成活动锁的报告,将锁类型显示为字符串名称.但是master..syslocks包含锁类型作为数字,它不包含这些名称 ; 如果确实如此,那将是一张严重失真的桌子!如果执行查询(Sybase ASE代码,则必须转换):

    SELECT *                    -- list LockTypes
        FROM master..spt_values 
        WHERE type = "L"
Run Code Online (Sandbox Code Playgroud)

您将在Lookup表中注意到66个LockType 数字名称.这允许sp_lock执行上面的Person :: Gender之类的简单代码:

    SELECT  spid,               -- list Active Locks
            DB_NAME(dbid),
            OBJECT_NAME(id, dbid),
            v.name,             -- expand lock name
            page,
            row
    FROM master..syslocks   L,
         master..spt_values LT
    WHERE L.type = LT.number    -- 
    AND   type = "L"            -- LockType Lookup table
    ORDER by 1, 2, 3, 4, 5, 6   -- such that perusal is easy
Run Code Online (Sandbox Code Playgroud)

投影

什么是(意思)Type ='P'?

什么是投影以及如何使用?

比如说,代替上面查询生成的活动锁,您需要一个包含所有 66个LockTypes 的列表,显示活动锁(或Null)的数量.您不需要游标或WHILE循环.我们可以项目投资中的LockType查找表,通过活动锁定计数:

    SELECT  LT.name,            -- list LockTypes
            [Count] = (         -- with count
        SELECT COUNT(*)
            FROM master..syslocks
            WHERE type = LT.number
                )
        FROM master..spt_values LT
        WHERE type = "L"
Run Code Online (Sandbox Code Playgroud)

有几种方法,只有一种.另一种方法是使用派生表而不是子查询.但是你仍然需要投影.

这通常spt_values是用于扩展或投影的内容.既然你知道它在那里,你也可以使用它.它是安全的(在master数据库中)并且几乎被所有系统程序使用,这意味着没有它就不能运行系统程序.

拆分列?

啊,你不明白"将一个CSV列分成多行"代码.

  • 忘掉spt_values片刻,再次检查一下代码.它只需要一个连续数字列表,这样就可以逐字节逐步浏览CSV列中的值列表.代码仅针对逗号或字符串结尾的每个字节激活.

  • 在哪里以SQL表的形式获得一组连续的数字,而不是从头开始创建一个并插入它?master..spt_values当然,为什么呢.如果你知道它在那里.

  • (您可以通过阅读系统存储过程的代码,了解一下ASE或SQL Server的内部结构.)

  • 请注意,一列中的任何CSV字段都是严重的标准化错误,它会中断2NF(包含重复值)和1NF(非原子).注意,没有打包或折叠,它是一个重复组,它是非规范化的.这种严重错误的许多负面后果之一是,不必使用简单的SQL将重复组导航为行,而是必须使用复杂的代码来确定和提取未规范化的CSV字段的内容.这里spt_values P为复杂代码提供了一个向量,使其更容易.

它有什么好处?

我想我已经回答了这个问题.如果你没有它,那么需要一个Numbers列表的每个系统过程都必须创建一个临时表; 并将行插入其中; 在运行其代码之前.当然,不必执行这些步骤,使系统过程更快.

现在,当您需要执行投影时,例如.您可以使用的日历日期或其他任何日期spt_values,而不是每次都必须创建自己的临时表(或创建自己的私有永久表并维护它).