SQL或TSQL Turing完成了吗?


171

这是今天在办公室提出的。我没有做这种事情的计划,但是理论上您可以用SQL编写编译器吗?乍一看,对我来说似乎是完整的,尽管对于许多类型的问题而言非常麻烦。

如果尚未完成,它将需要什么?

注意:我不想做任何事情,例如用SQL编写编译器,我知道这样做是很愚蠢的,因此,如果我们能够避免这种讨论,我将不胜感激。

Answers:


219

事实证明,即使没有真正的“脚本”扩展,例如PL / SQL或PSM(它们被设计为真正的编程语言,也有点作弊),SQL仍可以是图灵完备的。

这组幻灯片中,安德鲁·吉尔特(Andrew Gierth)通过构造一个循环标记系统证明了CTE和Windowing SQL是Turing Complete ,它被证明是Turing Complete。CTE功能是重要的部分-它允许您创建可以引用自身的命名子表达式,从而递归解决问题。

需要注意的有趣一点是,并未真正添加CTE来将SQL转换为编程语言-只是将声明性查询语言转换为更强大的声明性查询语言。在C ++中有点像C ++,尽管它们并非旨在创建元编程语言,但其模板却是图灵完整的。

哦,在SQL示例中设置Mandelbrot也非常令人印象深刻:)


1
Oracle SQL也正在完善,尽管其病态相当严重
Jens Schauder

2
>事实证明SQL不应该说:事实证明SQL:1999?只是说这是因为热膨胀系数是在99版本中增加和太多的人标准的SQL和Sql 92.关联
埃内斯托

1
@JensSchauder可以推广为“ Oracle $ technology是$ some_good_feature,尽管以一种相当恶心的方式”
Rob Grant

3
已经9年了,但这可能很有趣beta.observablehq.com/@pallada-92/sql-3d-engine
Loupax

33

如果可以证明给定的编程语言在计算上等效于图灵机,则该语言被认为是图灵完备的。

TSQL已完成,因为我们可以在TSQL中创建BrainFuck解释器。

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

那是图灵完整的事务处理SQL,我知道不是TC的ANSI SQL。但是努力!
alimack

28

https://web.archive.org/web/20110807062050/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本身是否合格也有待商debate。有人声称,任何告诉计算机做什么的代码段都可以视为一种编程语言。按照这个定义,SQL92是一个,例如HTML。这个定义很模糊,而且争论不了什么。


15

严格来说,由于最新的SQL标准包括“持久存储模块”(PSM),因此SQL现在是一种图灵完整的语言。简而言之,PSM是Oracle中PL / SQL语言的标准版本(以及当前DBMS的其他类似过程扩展)。

通过包含这些PSM,SQL变得完整了


13

ANSI select语句(最初在SQL-86中定义)不会完全完成,因为它始终会终止(递归CTE除外,并且仅在实现支持任意深度递归的情况下)。因此,不可能模拟任何其他图灵机。存储过程已经完成,但是多数民众赞成在作弊;-)


1

Oracle的PLSQL和Microsoft的TSQL都已经完成。Oracle的select语句本身也将完成。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.