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.

Matthew Vines
fonte

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 :)

Jan de Vos
fonte
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
Miroslav Popov
fonte
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.

Aiden Bell
fonte
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

Jordi Cabot
fonte
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 ;-)

usr
fonte
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.

sahossaini
fonte