Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Por que (e como) dividir a coluna usando master..spt_values?

Propósito


Por que usar master..spt-values não documentados

Sybase, e portanto seu filho bastardo MS SQL, fornecem vários recursos e funções para o produto, que é implementado em procedimentos do sistema (ao contrário dos binários como sqlserver, que são iniciados como um serviço). Esses procedimentos de procedimentos do sistema são escritos em código SQL e denominados sp_%. Exceto por alguns internos secretos, eles têm as mesmas limitações e necessidades que qualquer outro código SQL. Eles fazem parte do produto Sybase ASE ou SQL Server. Como tal, eles não são obrigatórios documentá-lo; e os bits internos não podem ser razoavelmente rotulados como "não documentados".

master..spt_values contém todos os vários bits e peças que os referidos procedimentos do sistema precisam, em uma tabela SQL, para produzir os vários relatórios. O sp significa procedimento do sistema; spt significa tabelas para procedimentos do sistema; e, claro, values é o conteúdo.

Tabelas de pesquisa


Qual ​​é o (significado de) Type ='P'

As pessoas geralmente descrevem spt_values como "desnormalizado", mas esse é o termo incorreto. O termo correto é dobrado , ou embalado . São 26 ou mais tabelas de pesquisa lógicas, cada uma lindamente normalizada, dobrada em uma tabela física, com um Type coluna para diferenciar as tabelas lógicas.

Agora, em um banco de dados normal, isso seria um erro grosseiro (basta olhar para as respostas para "uma tabela de pesquisa ou muitas"). Mas em um catálogo de servidores, é desejável que substitua 26 tabelas físicas.

  • "L" significa LockType Lookup; "V" significa DeviceType Lookup (V é a abreviação de Device em todo o servidor); etc. O tipo "P2" contém ordinais bit a bit, para a expansão de bits que são compactados em um INT.

  • É necessário um conjunto de números consecutivos dentro de limites conhecidos, disponíveis na forma de uma tabela SQL, para realizar uma Projeção, o que muitos dos procedimentos do sistema têm que fazer. O tipo "P" é uma lista de números consecutivos entre 0 e 2047.

  • O termo Projeção é usado aqui como o significado tecnicamente preciso, o sentido lógico natural, não o significado da álgebra relacional, que não é natural.

Portanto, há apenas um propósito para spt_values, para conter 26 tabelas de referência dobradas, de outra forma separadas, e uma tabela de projeção.

Expansão


O uso comum de spt_values então, é como uma pesquisa ou referência comum ou ENUM tabela. Primeiro, os valores de pesquisa:
    SELECT *                    -- list Genders
        FROM Gender 

É usado da mesma forma que Person tem um GenderCode que precisa ser expandido (muito expandido, esses dias esquisitos):
    SELECT  P.*,                -- list Person
            G.Name              -- expand GenderCode to Name
        FROM Person P
        JOIN Gender G
            ON P.GenderCode = G.GenderCode

Por exemplo. sp_lock produz um relatório de bloqueios ativos, exibindo os tipos de bloqueio como string nomes . Mas master..syslocks contém tipos de bloqueio como números , ele não contém esses nomes; e se o fizesse, seria uma tabela mal desnormalizada! Se você executar a consulta (código Sybase ASE, você terá que converter):
    SELECT *                    -- list LockTypes
        FROM master..spt_values 
        WHERE type = "L"

você notará 66 LockType números e nomes na tabela de pesquisa. Isso permite que sp_lock para executar código simples como Person::Gender acima:
    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

Projeção


Qual ​​é o (significado de) Type ='P' ?

O que é Projeção e como é usada?

Digamos, por exemplo, em vez dos bloqueios ativos produzidos pela consulta acima, você deseja uma lista de todos 66 LockTypes, mostrando o número de bloqueios ativos (ou Null). Você não precisa de um cursor ou de um WHILE ciclo. Poderíamos Projetar a tabela de pesquisa LockType, através de a contagem de bloqueios ativos:
    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"

Existem vários métodos, esse é apenas um. Outro método é usar uma Tabela Derivada em vez da Subconsulta. Mas você ainda precisa da Projeção.

Isso é normalmente o que spt_values é usado para Expansão ou Projeção. Agora que você sabe que está lá, você também pode usá-lo. É seguro (no master banco de dados) e usado por praticamente todos os procedimentos do sistema, o que significa que os procedimentos do sistema não podem ser executados sem ele.

para dividir uma coluna?

Ah, você não entende o código "Dividir uma coluna CSV em várias linhas".

  • Esqueça os spt_values por um momento e examine esse código novamente. Ele só precisa de uma lista de números consecutivos, para que possa percorrer a lista de valores na coluna CSV, byte a byte. O código é ativado apenas para cada byte que é uma vírgula ou fim de string.

  • Onde obter um conjunto de números consecutivos na forma de uma tabela SQL, em vez de criar um do zero e inserir nele? Por que, master..spt_values é claro. Se você sabe que existe.

  • (Você pode aprender um pouco sobre os componentes internos do ASE ou SQL Server, apenas lendo o código dos procedimentos armazenados do sistema.)

  • Observe que qualquer campo CSV em uma coluna é um erro de normalização grosseiro, ele quebra 2NF (contém valores repetidos) e 1NF (não atômico). Observe que não é embalado ou dobrado, é um grupo de repetição, não é normalizado. Uma das muitas consequências negativas de um erro tão grave é que, em vez de usar SQL simples para navegar no grupo de repetição como linhas, é preciso usar um código complexo para determinar e extrair o conteúdo do campo CSV não normalizado. Aqui spt_values P fornece um vetor para esse código complexo, tornando-o mais fácil.

Qual ​​é a vantagem disso?

Acho que respondi isso. Se você não o tivesse, todo procedimento do sistema que requer uma lista de Numbers teria que CRIAR uma tabela temporária; e INSERT as linhas nele; antes de executar seu código. É claro que não ter que executar essas etapas torna os procedimentos do sistema muito mais rápidos.

Agora, quando você precisa realizar uma projeção, por exemplo. datas do calendário no futuro, ou qualquer outra coisa, você pode usar spt_values , em vez de ter que criar sua própria tabela temporária a cada vez (ou criar sua própria tabela permanente privada e mantê-la).