これは今日オフィスで思いついた。私はそのようなことをする予定はありませんが、理論的にはSQLでコンパイラを書くことができますか?一見したところ、多くの種類の問題にとって非常に厄介ですが、完全に対処しているように見えます。
それが完全に実現しない場合、それがそうなるには何が必要ですか?
注:SQLでコンパイラーを作成するようなことはしたくありません。ばかげたことであることはわかっているので、その議論を回避できればありがたいです。
これは今日オフィスで思いついた。私はそのようなことをする予定はありませんが、理論的にはSQLでコンパイラを書くことができますか?一見したところ、多くの種類の問題にとって非常に厄介ですが、完全に対処しているように見えます。
それが完全に実現しない場合、それがそうなるには何が必要ですか?
注:SQLでコンパイラーを作成するようなことはしたくありません。ばかげたことであることはわかっているので、その議論を回避できればありがたいです。
回答:
PL / SQLやPSMなどの真の「スクリプト」拡張機能がなくても、SQLは完全にチューリングコンプリートであることがわかります(これらは、真のプログラミング言語として設計されているため、これはちょっとごまかしです)。
でスライドのこのセットアンドリューGierthは、CTEとウィンドウイングSQLを構築することにより、完全なチューリングされていることを証明している巡回タグシステムチューリング完全であることが証明されています、。ただし、CTE機能は重要な部分です。この機能を使用すると、自分自身を参照できる名前付きサブ式を作成して、問題を再帰的に解決できます。
注意すべき興味深い点は、SQLをプログラミング言語に変えるためにCTEが実際に追加されたのではなく、宣言型クエリ言語をより強力な宣言型クエリ言語に変えることだけです。C ++のようなもので、メタプログラミング言語を作成することを意図していないにもかかわらず、テンプレートがチューリング完全であることが判明しました。
与えられたプログラミング言語は、それが計算上チューリングマシンと同等であることを示すことができる場合、チューリング完全であると言われます。
TSQLでBrainFuckインタープリターを作成できるため、TSQLは完全なチューリングです。
提供されたコードはメモリ内で動作し、データベースを変更しません。
-- 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(つまり、SQL92標準)は完全に整えられていません。ただし、OracleのPL / SQLやSQL ServerのT-SQLなど、SQLから派生した言語の多くは完全に完成しています。
PL / SQLとT-SQLは確かにプログラミング言語としての資格があります。SQL92自体が資格を持つかどうかは議論の余地があります。一部の人々は、コンピュータに何をすべきかを指示するコードはプログラミング言語としての資格があると主張しています。その定義では、SQL92は1つですが、たとえばHTMLも1つです。定義はややあいまいであり、議論するのは無意味です。
厳密に言えば、最新のSQL標準には「Persistent Stored Modules」(PSM)が含まれているため、SQLは今では完全に完全な言語になっています。つまり、PSMはOracleのPL / SQL言語の標準バージョン(および現在のDBMSの他の同様の手続き型拡張機能)です。
これらのPSMを含めることで、SQLは完全に機能するようになりました