Чи завершено SQL або навіть TSQL Turing?


171

Це придумали сьогодні в офісі. У мене немає планів робити таке, але теоретично ви могли б написати компілятор у SQL? На перший погляд, мені здається, що це цілком повно, хоча і надзвичайно громіздко для багатьох класів проблем.

Якщо вона не є повною, що потрібно для того, щоб стати таким?

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

Відповіді:


219

Виявляється, SQL може бути Turing Complete навіть без справжнього розширення 'scripting', такого як PL / SQL або PSM (які розроблені так, щоб вони були справжніми мовами програмування, тому це начебто обман).

У цьому наборі слайдів Ендрю Гірт доводить, що за допомогою CTE та Windowing SQL є Turing Complete, побудувавши циклічну систему тегів , яка була доведена як Turing Complete. Однак функція CTE є важливою частиною - вона дозволяє створювати названі під вирази, які можуть посилатися на себе, і тим самим рекурсивно вирішувати проблеми.

Цікаво зазначити, що CTE насправді не додано для перетворення SQL в мову програмування - просто для перетворення декларативної мови запиту в більш потужну мову декларативного запиту. На зразок, як у C ++, шаблони яких виявились Тюрінг завершеними, хоча вони не мали наміру створювати мову програмування мета.

О, набір Мандельброта в прикладі SQL також дуже вражає :)


1
Oracle SQL також є повноцінним, хоча і досить хворим: blog.schauderhaft.de/2009/06/18/…
Jens

2
> Виходить, що SQL не повинен говорити: Виходить, що SQL: 1999? Просто кажучи про це, оскільки CTE були додані у версії 99, і тому що занадто багато людей асоціюють стандартний sql з Sql 92.
Ернесто

1
@JensSchauder, який можна узагальнити до "технології Oracle $ - це $ some_good_feature, хоча в досить хворій формі"
Роб Грант

3
Минуло 9 років, але це може бути цікаво beta.observablehq.com/@pallada-92/sql-3d-engine
Loupax

33

Кажуть, що дана мова програмування є повною Тьюрінгом, якщо можна показати, що вона обчислювально еквівалентна машині Тюрінга.

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

Це транзакційний SQL, який є Тьюрінг завершеним, ANSI SQL, який я зрозумів, не є TC. Але хороших зусиль!
alimack

28

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

Чи обговорення цієї теми. Цитата:

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

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


15

Власне кажучи, SQL тепер є повноцінною мовою, оскільки останній стандарт SQL включає "Постійні збережені модулі" (PSM). Коротше кажучи, PSM - це стандартна версія мови PL / SQL в Oracle (та інші подібні процедурні розширення поточних СУБД).

З включенням цих PSM, SQL став завершеним


13

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


1

PLSQL Oracle та TSQL Microsoft - це завершення. Сама заява Oracle щодо вибору також закінчується.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.