SQL hay thậm chí TSQL Turing đã hoàn thành?


171

Điều này đã đến tại văn phòng ngày hôm nay. Tôi không có kế hoạch làm một việc 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 bằng SQL không? Thoạt nhìn có vẻ như tôi đã hoàn thành việc này, mặc dù cực kỳ cồng kềnh đối với nhiều loại vấn đề.

Nếu nó không hoàn thành, nó đòi hỏi phải 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 trình biên dịch bằng SQL, tôi biết đó sẽ là một việc ngớ ngẩn, vì vậy nếu chúng ta có thể tránh cuộc thảo luận đó, tôi sẽ đánh giá cao nó.

Câu trả lời:


219

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

Trong tập hợp các slide này, 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 hệ thống thẻ tuần hoàn , đã được chứng minh là Turing Complete. Tuy nhiên, tính năng CTE là phần quan trọng - nó cho phép bạn tạo các biểu thức con có tên có thể tự tham chiếu và từ đó giải quyết các vấn đề theo cách đệ quy.

Đ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 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. Giống như trong C ++, có các mẫu hóa ra là Turing hoàn chỉnh mặc dù chúng không có ý định tạo ngôn ngữ lập trình meta.

Ồ, bộ Mandelbrot trong ví dụ SQL cũng rất ấn tượng :)


1
Oracle SQL cũng đã hoàn tất, mặc dù theo một cách khá bệnh hoạn: blog.schauderhaft.de/2009/06/18/ mẹo
Jens Schauder

2
> Hóa ra SQL không nên nói: Hóa ra 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à quá nhiều người liên kết sql tiêu chuẩn với Sql 92.
Ernesto

1
@JensSchauder có thể được khái quát thành "Công nghệ Oracle $ là $ some_good_feature, mặc dù theo một cách khá bệnh hoạn"
Rob Grant

3
Đã 9 năm nhưng đây có thể là phiên bản beta
Loupax

33

Một ngôn ngữ lập trình nhất định được gọi là Turing-Complete nếu có thể chỉ ra rằng nó tương đương với máy tính Turing.

TSQL là Turing Complete vì chúng tôi có thể tạo trình thông dịch BrainFuck trong TSQL.

Trình thông dịch BrainFuck bằng SQL - GitHub

Mã được cung cấp hoạt động trong bộ nhớ và không sửa đổi cơ sở dữ liệu.

-- 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

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

27

https://web.archive.org/web/20110807062050/http://channel9.msdn.com/forums/Tech Offer/431432-Query-Turing-Completuity-question

Là một cuộc thảo luận về chủ đề này. Một câu trích dẫn:

SQL như vậy (tức là tiêu chuẩn SQL92) không hoàn thành. Tuy nhiên, nhiều ngôn ngữ có nguồn gốc từ SQL, chẳng hạn như T / SQL của Oracle và T-SQL của Oracle Server và các ngôn ngữ khác đã hoàn tất.

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


15

Nói một cách chính xác, SQL hiện là một ngôn ngữ hoàn chỉnh vì tiêu chuẩn SQL mới nhất bao gồm "Các mô-đun được lưu trữ liên tục" (PSM). Nói tóm lại, PSM là phiên bản tiêu 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 các PSM này, SQL đã hoàn tất


13

Một câu lệnh chọn ANSI, như được định nghĩa ban đầu trong SQL-86, không hoàn thành vì nó luôn chấm dứt (ngoại trừ các CTE đệ quy và chỉ khi việc triển khai hỗ trợ đệ quy sâu tùy ý). 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 tất nhưng đó là gian lận ;-)


1

Cả PLQL của Oracle và TSQL của Microsoft đều đang hoàn tất. Bản thân tuyên bố chọn của Oracle cũng đã hoàn tất.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.