2009-05-22 14 views
115

Điều này đã xuất hiện tại văn phòng ngày hôm nay. Tôi không có kế hoạch làm một điều như vậy, nhưng về mặt lý thuyết bạn có thể viết một trình biên dịch trong SQL không? Thoạt nhìn nó xuất hiện với tôi để được turing hoàn thành, mặc dù rất cồng kềnh cho nhiều lớp học của các vấn đề.SQL hoặc thậm chí TSQL Turing có hoàn thành không?

Nếu nó không hoàn chỉnh, nó sẽ yêu cầu gì để trở thành như vậy? Lưu ý: Tôi không muốn làm bất cứ điều gì như viết một trình biên dịch trong SQL, tôi biết nó sẽ là một điều ngớ ngẩn để làm, vì vậy nếu chúng ta có thể tránh được cuộc thảo luận đó, tôi sẽ đánh giá cao nó.

Trả lời

157

Nó chỉ ra rằng SQL có thể là Turing Complete ngay cả khi không có phần mở rộng 'scripting' thực sự như PL/SQL hoặc PSM (được thiết kế là ngôn ngữ lập trình thực) đó là kinda gian lận).

Trong this set of slides Andrew Gierth chứng minh rằng với CTE và Windowing SQL là Turing Complete, bằng cách xây dựng một cyclic tag system, đã được chứng minh là Turing Complete. Tính năng CTE là một phần quan trọng tuy nhiên - nó cho phép bạn tạo ra các biểu thức con được đặt tên có thể tự giới thiệu, và do đó đệ quy giải quyết các vấn đề.

Điều thú vị cần lưu ý là CTE không thực sự được thêm vào để biến SQL thành ngôn ngữ lập trình - chỉ để biến một ngôn ngữ truy vấn khai báo thành ngôn ngữ truy vấn khai báo mạnh mẽ hơn. Sắp xếp giống như trong C++, có các khuôn mẫu hóa ra là Turing hoàn chỉnh mặc dù chúng không có ý định tạo ra một ngôn ngữ lập trình meta.

Oh, ví dụ Mandelbrot set in SQL là rất ấn tượng, cũng :)

+0

Oracle SQL cũng được Turing hoàn tất, mặc dù theo một cách khá ốm: http://blog.schauderhaft.de/2009/06/18/building-a-turing-engine-in -oracle-sql-using-the-model-clause/ –

+1

> Nó chỉ ra rằng SQL Không nên nói: Nó chỉ ra rằng SQL: 1999? Chỉ cần nói điều này bởi vì CTE được thêm vào trong phiên bản 99 và cách quá nhiều người kết hợp sql chuẩn với Sql 92. – Ernesto

+0

@JensSchauder có thể được khái quát hóa thành "Công nghệ $ Oracle là $ some_good_feature, mặc dù theo cách khá ốm" –

27

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

Thảo luận về chủ đề này. Báo giá:

SQL như vậy (nghĩa là tiêu chuẩn SQL92) không được hoàn tất. Tuy nhiên, nhiều ngôn ngữ bắt nguồn từ SQL, chẳng hạn như PL/SQL của Oracle và T2 SQL của SQL Server và các ngôn ngữ khác được hoàn tất.

PL/SQL và T-SQL chắc chắn đủ điều kiện làm ngôn ngữ lập trình, cho dù bản thân SQL92 đủ điều kiện mở để tranh luận. Một số người cho rằng bất kỳ đoạn mã nào nói với máy tính phải làm gì đủ điều kiện làm ngôn ngữ lập trình; theo định nghĩa đó, SQL92 là một, nhưng vd. HTML. Định nghĩa khá mơ hồ, và nó là một điều vô nghĩa để tranh luận.

12

Nói đúng, SQL bây giờ là ngôn ngữ hoàn chỉnh vì tiêu chuẩn SQL mới nhất bao gồm "Mô-đun lưu trữ liên tục" (PSM). Tóm lại, PSM là phiên bản chuẩn của ngôn ngữ PL/SQL trong Oracle (và các phần mở rộng thủ tục tương tự khác của DBMS hiện tại).

Với sự bao gồm của những PSMS, SQL trở thành Turing hoàn

11

Một ANSI lựa chọn công bố, như ban đầu được xác định trong SQL-86, không Turing hoàn chỉnh vì nó luôn luôn kết thúc (trừ CTEs đệ quy và chỉ khi thực hiện hỗ trợ tùy ý đệ quy sâu). Do đó, không thể mô phỏng bất kỳ máy turing nào khác. Các thủ tục được lưu trữ hoàn chỉnh nhưng điều đó gian lận ;-)

18

Các TSQL là Turing Complete.To chứng minh điều đó tôi đã thực hiện một thông dịch viên 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

là Turing hoàn chỉnh, ANSI SQL tôi hiểu không phải là TC. Nhưng nỗ lực tốt! – alimack