SQL или даже TSQL Тьюринг завершен? - PullRequest
151 голосов
/ 23 мая 2009

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

Если он не завершен по Тьюрингу, что бы он потребовал, чтобы стать таким?

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

Ответы [ 5 ]

200 голосов
/ 28 сентября 2011

Оказывается, что SQL может быть завершен по Тьюрингу даже без настоящего расширения «сценариев», такого как PL / SQL или PSM (которые предназначены для настоящих языков программирования, так что это своего рода обман).

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

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

Ох, пример Мандельброта в SQL тоже впечатляет:)

28 голосов
/ 18 января 2016

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

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
26 голосов
/ 23 мая 2009

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

Это обсуждение этой темы. Цитата:

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

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

13 голосов
/ 23 мая 2009

Строго говоря, SQL теперь является полным языком Тьюринга, поскольку последний стандарт SQL включает в себя «Постоянные хранимые модули» (PSM). Короче говоря, PSM является стандартной версией языка PL / SQL в Oracle (и других подобных процедурных расширений текущей СУБД).

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

12 голосов
/ 24 июля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...