O SQL ou mesmo o TSQL Turing Complete?


171

Isso surgiu no escritório hoje. Não tenho planos de fazer isso, mas teoricamente você poderia escrever um compilador no SQL? À primeira vista, parece-me completo, embora extremamente complicado para muitas classes de problemas.

Se não estiver completo, o que seria necessário?

Nota: Não desejo fazer nada como escrever um compilador no SQL, sei que seria uma coisa boba de se fazer, portanto, se pudermos evitar essa discussão, eu apreciaria.

Respostas:


219

Acontece que o SQL pode ser Turing Complete, mesmo sem uma extensão de 'script' verdadeira, como PL / SQL ou PSM (que são projetadas para serem verdadeiras linguagens de programação, então é meio trapaceiro).

Em este conjunto de slides Andrew Gierth prova que com CTE e Windowing SQL é Turing completa, através da construção de um sistema de tag cíclica , que tem provado ser Turing completa. No entanto, o recurso CTE é a parte importante - permite criar sub-expressões nomeadas que podem se referir a elas mesmas e, assim, resolver problemas recursivamente.

O interessante é notar que o CTE não foi realmente adicionado para transformar o SQL em uma linguagem de programação - apenas para transformar uma linguagem de consulta declarativa em uma linguagem de consulta declarativa mais poderosa. Mais ou menos como em C ++, cujos modelos acabaram por ser Turing completos, mesmo que eles não tivessem a intenção de criar uma linguagem de programação meta.

Ah, o Mandelbrot definido no exemplo SQL também é muito impressionante :)


1
O Oracle SQL também está completo, embora de uma maneira um tanto desagradável
Jens Schauder

2
> Acontece que SQL Não deveria dizer: Acontece que SQL: 1999? Só estou dizendo isso porque os CTEs foram adicionados na versão 99 e muitas pessoas associam o sql padrão ao Sql 92.
Ernesto

1
@JensSchauder que podem ser generalizados para "A Oracle $ tecnologia é de R $ some_good_feature, embora de uma forma bastante doente"
Rob Grant

3
Tem sido 9 anos, mas isso pode ser interessante beta.observablehq.com/@pallada-92/sql-3d-engine
Loupax

33

Diz-se que uma determinada linguagem de programação é completa em Turing se for demonstrado que é computacionalmente equivalente a uma máquina de Turing.

O TSQL é Turing Complete porque podemos fazer um intérprete BrainFuck no TSQL.

Intérprete de BrainFuck em SQL - GitHub

O código fornecido funciona na memória e não modifica um banco de dados.

-- Brain Fuck interpreter in SQL

DECLARE @Code  VARCHAR(MAX) = ', [>,] < [.<]'
DECLARE @Input VARCHAR(MAX) = '!dlroW olleH';

-- Creates a "BrainFuck" DataBase.
-- CREATE DATABASE BrainFuck;

-- Creates the Source code table
DECLARE @CodeTable TABLE (
    [Id]      INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
    [Command] CHAR(1) NOT NULL
);

-- Populate the source code into CodeTable
DECLARE @CodeLen INT = LEN(@Code);
DECLARE @CodePos INT = 0;
DECLARE @CodeChar CHAR(1);

WHILE @CodePos < @CodeLen
BEGIN
    SET @CodePos  = @CodePos + 1;
    SET @CodeChar = SUBSTRING(@Code, @CodePos, 1);
    IF @CodeChar IN ('+', '-', '>', '<', ',', '.', '[', ']')
        INSERT INTO @CodeTable ([Command]) VALUES (@CodeChar)
END

-- Creates the Input table
DECLARE @InputTable TABLE (
    [Id]   INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
    [Char] CHAR(1) NOT NULL
);

-- Populate the input text into InputTable
DECLARE @InputLen INT = LEN(@Input);
DECLARE @InputPos INT = 0;

WHILE @InputPos < @InputLen
BEGIN
    SET @InputPos = @InputPos + 1;
    INSERT INTO @InputTable ([Char])
    VALUES (SUBSTRING(@Input, @InputPos, 1))
END

-- Creates the Output table
DECLARE @OutputTable TABLE (
    [Id]   INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
    [Char] CHAR(1) NOT NULL
);

-- Creates the Buffer table
DECLARE @BufferTable TABLE (
    [Id]     INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
    [Memory] INT DEFAULT 0  NOT NULL
);
INSERT INTO @BufferTable ([Memory])
VALUES (0);

-- Initialization of temporary variables 
DECLARE @CodeLength INT = (SELECT COUNT(*) FROM @CodeTable);
DECLARE @CodeIndex  INT = 0;
DECLARE @Pointer    INT = 1;
DECLARE @InputIndex INT = 0;
DECLARE @Command    CHAR(1);
DECLARE @Depth      INT;

-- Main calculation cycle
WHILE @CodeIndex < @CodeLength
BEGIN
    -- Read the next command.
    SET @CodeIndex = @CodeIndex + 1;
    SET @Command = (SELECT [Command] FROM @CodeTable WHERE [Id] = @CodeIndex);

    -- Increment the pointer.
    IF @Command = '>'
    BEGIN
        SET @Pointer = @Pointer + 1;
        IF (SELECT [Id] FROM @BufferTable WHERE [Id] = @Pointer) IS NULL
            INSERT INTO @BufferTable ([Memory]) VALUES (0);
    END

    -- Decrement the pointer.
    ELSE IF @Command = '<'
        SET @Pointer = @Pointer - 1;

    -- Increment the byte at the pointer.
    ELSE IF @Command = '+'
        UPDATE @BufferTable SET [Memory] = [Memory] + 1 WHERE [Id] = @Pointer;

    -- Decrement the byte at the pointer.
    ELSE IF @Command = '-'
        UPDATE @BufferTable SET [Memory] = [Memory] - 1 WHERE [Id] = @Pointer;

    -- Output the byte at the pointer.
    ELSE IF @Command = '.'
        INSERT INTO @OutputTable ([Char]) (SELECT CHAR([Memory]) FROM @BufferTable WHERE [Id] = @Pointer);

    -- Input a byte and store it in the byte at the pointer.
    ELSE IF @Command = ','
    BEGIN
        SET @InputIndex = @InputIndex + 1;
        UPDATE @BufferTable SET [Memory] = COALESCE((SELECT ASCII([Char]) FROM @InputTable WHERE [Id] = @InputIndex), 0) WHERE [Id] = @Pointer;
    END

    -- Jump forward past the matching ] if the byte at the pointer is zero.
    ELSE IF @Command = '[' AND COALESCE((SELECT [Memory] FROM @BufferTable WHERE [Id] = @Pointer), 0) = 0
    BEGIN
        SET @Depth = 1;
        WHILE @Depth > 0
        BEGIN
            SET @CodeIndex = @CodeIndex + 1;
            SET @Command = (SELECT [Command] FROM @CodeTable WHERE [Id] = @CodeIndex);
            IF @Command = '[' SET @Depth = @Depth + 1;
            ELSE IF @Command = ']' SET @Depth = @Depth - 1;
        END
    END

    -- Jump backwards to the matching [ unless the byte at the pointer is zero.
    ELSE IF @Command = ']' AND COALESCE((SELECT [Memory] FROM @BufferTable WHERE [Id] = @Pointer), 0) != 0
    BEGIN
        SET @Depth = 1;
        WHILE @Depth > 0
        BEGIN
            SET @CodeIndex = @CodeIndex - 1;
            SET @Command = (SELECT [Command] FROM @CodeTable WHERE [Id] = @CodeIndex);
            IF @Command = ']' SET @Depth = @Depth + 1;
            ELSE IF @Command = '[' SET @Depth = @Depth - 1;
        END
    END
END;

-- Collects and prints the output
DECLARE @Output VARCHAR(MAX);
SELECT @Output = COALESCE(@Output, '') + [Char]
FROM @OutputTable;

PRINT @Output;
Go

Isso é transact SQL, que é Turing completo, ANSI SQL entendi que não é TC. Mas bom esforço!
Alimack

28

https://web.archive.org/web/20110807062050/http://channel9.msdn.com/forums/TechOff/431432-SQL-Turing-Completeness-question

É uma discussão sobre este tópico. Uma citação:

O SQL como tal (ou seja, o padrão SQL92) não está completo. No entanto, muitas das linguagens derivadas do SQL, como PL / SQL da Oracle e T-SQL do SQL Server, entre outras, estão completas.

O PL / SQL e o T-SQL certamente se qualificam como linguagens de programação, se o próprio SQL92 se qualifica está aberto para debate. Algumas pessoas afirmam que qualquer parte do código que diz ao computador o que fazer se qualifica como uma linguagem de programação; por essa definição, SQL92 é um, mas o mesmo ocorre, por exemplo, em HTML. A definição é bastante vaga, e é uma coisa inútil para discutir.


15

A rigor, o SQL agora é uma linguagem completa, porque o último padrão SQL inclui os "Módulos armazenados persistentes" (PSMs). Em resumo, um PSM é a versão padrão da linguagem PL / SQL no Oracle (e outras extensões procedurais semelhantes do DBMS atual).

Com a inclusão desses PSMs, o SQL tornou-se completo


13

Uma instrução de seleção ANSI, conforme definida originalmente no SQL-86, não fica completa porque sempre é finalizada (exceto CTEs recursivas e apenas se a implementação oferecer suporte a recursões arbitrariamente profundas). Portanto, não é possível simular nenhuma outra máquina de turing. Os procedimentos armazenados estão completos, mas isso é trapaça ;-)


1

O PLSQL da Oracle e o TSQL da Microsoft estão completos. A própria instrução select da Oracle também está completa.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.