2009-05-22 21 views
115

Esto se presentó hoy en la oficina. No tengo planes de hacer tal cosa, pero teóricamente podría escribir un compilador en SQL? A primera vista, me parece completamente completo, aunque extremadamente engorroso para muchas clases de problemas.¿Está SQL o incluso TSQL Turing Complete?

Si no está completo, ¿qué necesitaría para serlo?

Nota: No tengo ningún deseo de hacer algo como escribir un compilador en SQL, sé que sería una tontería, así que si podemos evitar esa discusión, lo agradecería.

Respuesta

157

Resulta que SQL puede ser Turing Complete incluso sin una verdadera extensión de 'scripting' como PL/SQL o PSM (que están diseñados para ser verdaderos lenguajes de programación, por lo que eso es un poco de trampa).

En this set of slides Andrew Gierth demuestra que con CTE y Windowing SQL es Turing Complete, mediante la construcción de un cyclic tag system, que ha demostrado ser Turing Complete. Sin embargo, la característica CTE es la parte más importante: le permite crear sub expresiones que pueden referirse a sí mismas y, por lo tanto, resolver problemas de forma recursiva.

Lo interesante a tener en cuenta es que CTE realmente no se agregó para convertir SQL en un lenguaje de programación, solo para convertir un lenguaje de consulta declarativa en un lenguaje de consulta declarativo más poderoso. Algo así como en C++, cuyas plantillas resultaron ser Turing completas, aunque no estaban destinadas a crear un metatexto de lenguaje.

Oh, el ejemplo Mandelbrot set in SQL es muy impresionante, así :)

+0

Oracle SQL también se Turing completo, aunque de un modo bastante enferma: http://blog.schauderhaft.de/2009/06/18/building-a-turing-engine-in -oracle-sql-using-the-model-clause/ –

+1

> Resulta que SQL No debería decir: Resulta que SQL: 1999? Solo digo esto porque los CTE se agregaron en la versión 99 y demasiadas personas asocian el sql estándar con el Sql 92. – Ernesto

+0

@JensSchauder que se puede generalizar a "Oracle $ la tecnología es $ alguna_buena_facilidad, aunque de una manera bastante enferma" –

27

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

es una discusión de este tema. Una cotización:

SQL como tal (es decir, el estándar SQL92) no está terminado. Sin embargo, muchos de los lenguajes derivados de SQL, tales como PL/SQL de Oracle y SQL Server's T-SQL y otros están completos.

PL/SQL y T-SQL ciertamente califican como lenguajes de programación, ya sea que SQL92 califique está abierto para debate. Algunas personas afirman que cualquier parte del código que le dice a una computadora qué hacer califica como un lenguaje de programación; según esa definición SQL92 es uno, pero también lo es, p. HTML. La definición es bastante vaga, y es inútil discutirlo.

12

Estrictamente hablando, SQL ahora es un lenguaje completo porque el último estándar SQL incluye los "Módulos almacenados persistentes" (PSM). En resumen, un PSM es la versión estándar del lenguaje PL/SQL en Oracle (y otras extensiones de procedimiento similares del DBMS actual).

Con la inclusión de estos PSM, SQL convirtió Turing completa

11

Un ANSI instrucción de selección, tal como se definió originalmente en SQL-86, no se turing completa porque siempre termina (a excepción de las CTE recursivas y sólo si la puesta en práctica admite recursiones arbitrariamente profundas). Por lo tanto, no es posible simular ninguna otra máquina de turing. Los procedimientos almacenados están completos pero eso es engañoso ;-)

18

El TSQL es Turing Complete.To demostrar que hice un intérprete BrainFuck.

BrainFuck interpreter in 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 backward 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 
+0

Esa es la transacción SQL que Turing está completo, ANSI SQL entendí que no es TC. ¡Pero buen esfuerzo! – alimack

Cuestiones relacionadas