¿Está SQL o incluso TSQL Turing Complete?
programming-languages language-features (5)
Esto apareció en la oficina hoy. 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.
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.
El TSQL es Turing Complete. Para demostrarlo, hice un intérprete de BrainFuck.
Intérprete BrainFuck en 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
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 se convirtió en completo
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, así que eso es un poco de engaño).
En este conjunto de diapositivas, Andrew Gierth demuestra que con CTE y Windowing SQL es Turing Complete, mediante la construcción de un sistema de etiquetas cíclicas , 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 no se agregó realmente para convertir SQL en un lenguaje de programación, solo para convertir un lenguaje de consulta declarativo 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 conjunto de Mandelbrot en el ejemplo SQL es muy impresionante, también :)
Una instrucción de selección ANSI, tal como se definió originalmente en SQL-86, no está completa porque siempre termina (excepto para los CTE recursivos y solo si la implementación admite la recursión arbitrariamente profunda). Por lo tanto, no es posible simular ninguna otra máquina de turing. Los procedimientos almacenados están completos pero eso es trampa ;-)
http://channel9.msdn.com/forums/TechOff/431432-SQL-Turing-Completeness-question/
Es una discusión de este tema. Una cita:
SQL como tal (es decir, el estándar SQL92) no está completo. Sin embargo, muchos de los lenguajes derivados de SQL, tales como PL / SQL de Oracle y T-SQL de SQL Server y otros están completos.
PL / SQL y T-SQL sin duda califican como lenguajes de programación, ya sea que SQL92 califique por sí solo está abierto para el 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; por esa definición, SQL92 es uno, pero también lo es, por ejemplo, HTML. La definición es bastante vaga, y es inútil discutirlo.