Является ли SQL или даже TSQL Turing завершен?

Это появилось сегодня в офисе. У меня нет планов делать такую ​​вещь, но теоретически вы могли бы написать компилятор в SQL? На первый взгляд мне кажется, что я считаю, что он завершен, хотя и очень громоздкий для многих проблем.

Если это не завершено, зачем ему это нужно?

Примечание. У меня нет желания делать что-либо вроде написания компилятора в SQL, я знаю, что это будет глупо, поэтому, если мы сможем избежать этого обсуждения, я был бы признателен.

Ответ 1

Оказывается, что SQL может быть Turing Complete даже без истинного расширения скриптов, такого как PL/SQL или PSM (которые предназначены для того, чтобы быть истинными языками программирования, так что любопытное обманывание).

В этот набор слайдов Эндрю Гирт доказывает, что с CTE и Windowing SQL является Turing Complete, построив циклическая система тегов, которая, как доказано, является Turing Complete. Однако функция CTE является важной частью - она ​​позволяет создавать именованные подвыражения, которые могут ссылаться на самих себя и тем самым рекурсивно решать проблемы.

Интересно отметить, что CTE не был добавлен, чтобы превратить SQL в язык программирования - просто чтобы превратить декларативный язык запросов в более мощный декларативный язык запросов. Похоже, что в С++, чьи шаблоны оказались завершенными, хотя они не были предназначены для создания мета-языка программирования.

О, пример Mandelbrot, установленный в SQL, очень впечатляет:)

Ответ 2

Данный язык программирования называется полным по Тьюрингу, если можно показать, что он вычислительно эквивалентен машине Тьюринга.

TSQL завершен по Тьюрингу, потому что мы можем создать интерпретатор BrainFuck на TSQL.

Интерпретатор BrainFuck в SQL - GitHub

Предоставленный код работает в памяти и не изменяет базу данных.

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

Ответ 3

http://channel9.msdn.com/forums/TechOff/431432-SQL-Turing-Completeness-question/

Обсуждается эта тема. Цитата:

SQL как таковой (т.е. стандарт SQL92) не завершен. Однако, многие языки, полученные из SQL, такие как Oracle PL/SQL и SQL Server T-SQL и другие завершены.

PL/SQL и T-SQL, безусловно, квалифицируются как языки программирования, независимо от того, подходит ли сам SQL92 для обсуждения. Некоторые люди утверждают, что любой фрагмент кода, который говорит компьютеру о том, что делать, квалифицируется как язык программирования; по этому определению SQL92 является одним, но так, например, HTML. Определение довольно расплывчато, и об этом бессмысленно спорить.

Ответ 4

Строго говоря, SQL теперь является полным языком, поскольку последний стандарт SQL включает в себя "Persistent Stored Modules" (PSM). Короче говоря, PSM - это стандартная версия языка PL/SQL в Oracle (и другие подобные процедурные расширения существующей СУБД).

С включением этих PSM SQL полностью завершил

Ответ 5

Оператор выбора ANSI, как первоначально было определено в SQL-86, не завершается полным, поскольку он всегда завершается (кроме рекурсивных CTE и только в том случае, если реализация поддерживает произвольно глубокую рекурсию). Поэтому невозможно смоделировать любую другую машину для turing. Хранимые процедуры завершаются, но обманывают; -)