Есть ли такая вещь, как переносимый SQL?

По моему опыту, хотя есть стандарт SQL, довольно сложно написать SQL, который работает, немодифицирован, по большому количеству РСУБД.

Таким образом, я хотел бы знать, есть ли подмножество SQL (включая DDL, схемы и т.д.), которое, как известно, работает на всех основных РСУБД, включая PostgreSQL, MySQL, SQL Server и, наконец, Oracle. Какие недостатки следует избегать при написании переносимого SQL?

Кстати, существует ли проект, целью которого является преобразование действительного подмножества SQL в конкретные диалекты, используемые всеми этими поставщиками? Я знаю, что Hibernate и другие ORM-системы должны это делать, но я не хочу ORM, я хочу написать прямой SQL-запрос.

Спасибо!

Ответ 1

Проблема заключается в том, что некоторые СУБД даже игнорируют самые простые стандарты (например, такие как цитирование символов или конкатенация строк).

Итак, следующая (100% ANSI SQL) не запускается на каждой СУБД:

UPDATE some_table
    SET some_column = some_column || '_more_data';

И я даже не думаю о более продвинутых стандартах SQL, таких как рекурсивные общие выражения таблиц (даже те, которые его поддерживают, не всегда соответствуют) или функции окон (некоторые из них реализуют очень узкое подмножество, некоторые не поддерживают все параметры).

Что касается DDL, возникает проблема с типами данных. DATE не везде везде, как TIMESTAMP. Не каждая СУБД имеет тип BOOLEAN или TIME.

Когда дело доходит до ограничений или доменов, вы получаете еще больше различий.

Итак, вкратце: если вы действительно, действительно должны быть независимыми от СУБД, не беспокойтесь об этом.

Сказав все это: если у вас есть выбор между проприетарным и стандартным синтаксисом, выберите стандартный синтаксис (OUTER JOIN vs (+) или *=, decode vs CASE, nvl vs. coalesce и т.д.).

Ответ 2

Внутри каждой СУБД все, что указано как ANSI-совместимый, должно быть одинаковым для всех из них, как это является истинным стандартом. Однако, придерживаясь только ANSI (то есть портативного) материала, вы теряете оптимизированную специфику для конкретного поставщика. Кроме того, только потому, что PostgreSQL реализует функцию ANSI, это не означает, что она доступна в любой другой СУБД (но если она доступна, то она должна работать одинаково).

Лично я не вижу никакой ценности в действительно переносимом SQL-коде или проекте для нормализации до самого низкого общего знаменателя, поскольку каждая конкретная RDBMS оптимизирована по-разному. Нет общего языка приложений. ЕСЛИ вы используете С#, тогда вы не захотите использовать материал, который можно найти только в PHP или JAVA. Так что просто включите платформу, на которой вы находитесь:).

Изменить: если вы пишете приложение, которое может подключаться к нескольким различным РСУБД, вам, вероятно, потребуется найти соответствующий SQL для каждой конкретной платформы, как и авторы каждого из ORM.

Ответ 3

Простые запросы почти всегда переносимы. К сожалению, список поставщиков SQL, которые вы предоставили, сильно зависит от соответствия стандартам. MS SQL Server находится на вершине тех, которые вы указали в терминах соответствия стандартам ANSI SQL, и как MySQL, так и Oracle, как известно, являются плохими, когда дело доходит до соблюдения стандартов. Это, конечно же, не означает, что они являются плохими системами RDBMS или что вы не можете писать с ними мощные запросы, но их соответствие стандартам не совсем то, что они известны.

Обратите внимание, что в этом списке вы опустили несколько крупных RDBMS-игроков, а именно Sybase и IBM DB2. Эти два, как правило, более совместимы со стандартами, чем другие, для чего это стоит.

Ответ 4

Идеал, который я могу написать SQL-код на одном продукте и ожидать, что он будет работать на другом без модификации, - это невозможный сон.

Я скорее думаю о "переносимости" как о том, насколько легко переносить код на другой продукт SQL или, что крайне важно, на более позднюю версию одного и того же продукта SQL, отмечая, что установленные продукты SQL имеют тенденцию двигаться к SQL Стандарты (например, SQL-92 UPDATE требуют, чтобы скалярные подзапросы были длинными, SQL Server на раннем этапе предоставлял проприетарный синтаксис JOIN..FROM, а затем для SQL Server 2008 предоставлял синтаксис MERGE, который поддерживает и расширяет стандартный SQL MERGE).

Как правило, используйте стандартный код SQL, где ваш SQL-продукт поддерживает его (например, CURRENT_TIMESTAMP, а не SQL Server getdate()), в противном случае предпочитает проприетарный код, который легко сопоставляется с стандартным кодом SQL (например, SQL Server SUBSTRING() легко сопоставляется с стандартным SQL SUBSTRING() с использованием макроса). Обратите внимание, что некоторые функции вне стандарта SQL будут распространены для SQL-продуктов (например, у большинства/всех будет функция или оператор MOD()).

Ответ 5

Я создаю веб-приложения, используя Alpha Five, которая имеет функцию под названием "Portable SQL". Существует около 200 функций портативности. Если я использую функцию переносимости, она автоматически преобразуется в собственный SQL, чтобы соответствовать любому моменту, который я использовал.

Итак, если я пишу "SELECT now() FROM clients", теперь() является функцией переносимости, этот синтаксис будет автоматически преобразован на родной язык, в зависимости от того, что я использую. Они поддерживают 22 разных SQL-модуля.

  • DB2-SELECT CURRENT TIMESTAMP AS Expr1 FROM client
  • MYSQL-SELECT Now() AS Expr1 FROM client
  • MSSQL-SELECT CURRENT_TIMESTAMP AS Expr1 FROM client
  • SYBASE-SELECT getdate() AS Expr1 FROM client
  • ODBC-SELECT {fn Теперь()} AS Expr1 FROM client