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

对我在这里重写的问题 “Split one column into multiple rows”的答案提出质疑[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,1)  = '') --this does not work correctly anyway

相关问题:

> What is the purpose of system table table master..spt_values and what are the meanings of its values?

解决方法

目的

为什么使用未记录的master..spt值

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

master..spt_values包含所有系统过程在sql表中需要的各种不同的部分,以生成各种报告. sp是系统程序; spt表示系统程序表;当然,价值观是内容.

查找表

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

人们经常将spt_values描述为“正规化”,但这是不正确的术语.正确的术语是折叠或包装的.它是26个左右的逻辑查找表,每个精美的规范化,折叠成一个物理表,使用“类型”列来区分逻辑表.

现在在正常的数据库中,这将是一个严重的错误(只是看一下“一个查找表或许多”的答案).但是在服务器目录中,最好替换26个物理表.

>“L”代表LockType Lookup; “V”表示DeviceType Lookup(V为整个服务器中的Device为简称);类型“P2”包含按位序号,用于扩展打包成INT的位.
>已知边界中的一组连续的数字,以sql表的形式提供是必需的,以便执行许多系统过程必须执行的“投影”.类型“P”是0到2047之间的连续数字的列表.
>术语“投影”在这里被用作技术上精确的意义,自然的逻辑意义,而不是关系代数的意义,这是不自然的.

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

扩张

通常使用spt_values,就像普通的Lookup或Reference或ENUM表.首先,Lookup值:

SELECT *                    -- list Genders
        FROM Gender

它的使用方式与Person具有需要扩展的GenderCode(非常扩展,这些奇怪的日子)相同:

SELECT  P.*,-- list Person
            G.Name              -- expand GenderCode to Name
        FROM Person P
        JOIN Gender G
            ON P.GenderCode = G.GenderCode

例如. sp_lock生成活动锁的报告,显示锁类型作为字符串名称.但是master..slocks包含锁定类型作为数字,它不包含这些名称;如果这样做,那将是一个严重的非正规化表!如果执行查询(Sybase ASE代码,则必须转换):

SELECT *                    -- list LockTypes
        FROM master..spt_values 
        WHERE type = "L"

您将在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,3,4,5,6   -- such that perusal is easy

投影

什么是(含义)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"

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

这通常是spt_values用于扩展或投影.现在你知道它在那里,你也可以使用它.它是安全的(在主数据库中),并被几乎所有的系统过程所使用,这意味着系统过程无法运行.

分割列?

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

>暂时忘记spt_values,再次检查该代码.它只需要一个连续数字的列表,以便可以逐个逐字节地逐列CSV列中的值列表.该代码只对每个字节都是激活,逗号或字符串结尾.
>在哪里可以以sql表的形式获取一组连续的数字,而不是从头开始创建一个数组,并将其插入到其中?为什么,master..spt_values当然是.如果你知道它在那里
(您可以通过阅读系统存储过程的代码了解一下ASE或sql Server的内部部分.)
>请注意,一列中的任何CSV字段都是总标准化错误,它打破2NF(包含重复值)和1NF(不是原子).注意,这是不包装或折叠的,它是一个重复组,它是不规范化的.这种严重错误的许多负面后果之一是,不是使用简单的sql将重复组导航为行,而是必须使用复杂代码来确定和提取未规范化的CSV字段的内容.这里spt_values P为该复杂代码提供了一个向量,使其更容易.

它的好处是什么?

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

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

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...