web-dev-qa-db-ja.com

SQLまたはTSQLチューリングは完全ですか?

これは今日オフィスで思いついた。私はそのようなことをする予定はありませんが、理論的にはSQLでコンパイラを書くことができますか?一見したところ、多くのクラスの問題にとっては非常に面倒ですが、完全にチューリングしているように見えます。

チューリングが完了していない場合、そうするには何が必要ですか?

注:SQLでコンパイラーを作成するようなことはしたくないので、やるのはばかげたことになるので、その議論を避けることができれば感謝します。

153
Matthew Vines

PL/SQLやPSMなどの真の「スクリプト」拡張機能がなくてもSQLはチューリングコンプリートになる可能性があることがわかります(真のプログラミング言語であるように設計されているため、ちょっとした不正行為です)。

このスライドのセット Andrew Gierthは、CTEとWindowing SQLで サイクリックタグシステム を構築することにより、チューリング完全であることを証明します。ただし、CTE機能は重要な部分です。これにより、自分自身を参照できる名前付きの部分式を作成でき、それにより問題を再帰的に解決できます。

興味深いのは、SQLをプログラミング言語に変えるためにCTEが実際に追加されたのではないことです。宣言クエリ言語をより強力な宣言クエリ言語に変えるためだけです。 C++のように、テンプレートはメタプログラミング言語を作成することを意図していませんでしたが、チューリング完全であることが判明しました。

ああ、 SQLで設定されたマンデルブロ の例も非常に印象的です:)

202
Jan de Vos

特定のプログラミング言語は、チューリングマシンと計算的に同等であることが示される場合、チューリング完全であると言われます。

TSQLで BrainFuck インタープリターを作成できるため、TSQLはチューリング完全です。

SQLのBrainFuckインタープリター-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
29
Miroslav Popov

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

このトピックの議論です。見積もり:

SQL自体(つまり、SQL92標準)は完全なチューリングではありません。ただし、OracleのPL/SQLやSQL ServerのT-SQLなど、SQLから派生した言語の多くは完全に調整されています。

PL/SQLとT-SQLは、SQL92自体が資格を満たしているかどうかは議論の余地がありますが、確かにプログラミング言語として資格があります。一部の人々は、何をすべきかをコンピューターに伝えるコードは、プログラミング言語としての資格があると主張しています。その定義により、SQL92は1つですが、 HTML。定義はかなり曖昧であり、議論するのは無意味です。

26
Aiden Bell

厳密に言えば、最新のSQL標準には "Persistent Stored Modules"(PSM)が含まれているため、SQLは完全な言語になりました。要するに、PSMはOracleのPL/SQL言語の標準バージョン(および現在のDBMSの他の同様の手続き拡張)です。

これらのPSMを含めることで、SQLは完全なチューリングになりました

13
Jordi Cabot

SQL-86で最初に定義されたANSI selectステートメントは、常に終了するため、完全なチューリングではありません(再帰CTEを除き、実装が任意の深い再帰をサポートする場合のみ)。したがって、他のチューリングマシンをシミュレートすることはできません。ストアドプロシージャは完全にチューリングされていますが、不正行為です;-)

12
usr