Приветствую, Nonmanual Worker, вы писали:
NW> Здравствуйте, Sheridan, Вы писали:
NW> S>Приветствую!
NW> S>Уважаемые, есть ли где-ть собранная воедино инфа про разницу в SQL диалектах разных БД?
NW> Слишком пространная информация вам нужна.
NW> Уточните, какие конкретно СУБД вас интересуют? Разница в чем конкретно — операторы, форма записи идентификаторов\строк? А то, например сравнивая MySQL 4 и Oracle 10, проще сказать что там общего.
Ну пока что postgresql, mysql, firebird и sqlite
С ddl в принципе я разобрался более менее, нужен sql. Пока что интересует вот что:
1. Типы данных bool, varchar, int, date, time, datetime, blob — да, ddl, но в принципе этот пункт неважен пока
2. Маскировка ключевых слов (ну к примеру в мускуле select * from `table` — не выдаст ошибку что мол table — кейворд)
3. Формат записи строк
Ну и прочие мелочи типа ограничения выборки. Может еще что добавите...
Пока что конструкции sql — простые, даже без джойнов.
Для чего:
Рисую для С++ (Qt) так сказать генератор sql под разные БД. Он-же будет и реструктуризатором базы.
Грубо говоря в коде будет чтототипа
CREATE_TABLE(forums);
APPEND_FIELD(forums, id, T_INTEGER); SET_UNIQUE(forums, id);
APPEND_FIELD(forums, groupid, T_INTEGER);
APPEND_FIELD(forums, shortname, T_STRING); SET_MAX_LENGTH(forums, shortname, 128);
APPEND_FIELD(forums, name, T_STRING);
APPEND_FIELD(forums, rated, T_BOOL);
APPEND_FIELD(forums, intop, T_BOOL);
APPEND_FIELD(forums, ratelimit, T_INTEGER);
APPEND_FIELD(forums, subscribed, T_BOOL); SET_DEFAULT(forums, subscribed, false);
SET_PRIMARY_KEY(forums, id);
APPEND_INDEX_FIELD(forums, id, idAsc);
APPEND_INDEX_FIELD(forums, groupid, idAsc);
APPEND_INDEX_FIELDS(forums, TABLE_FIELD(forums, shortname) << TABLE_FIELD(forums, name), idAsc);
//--------------
SELECT(get_forums);
FIELD(get_forums, forums, name);
FIELD(get_forums, forums, shortname);
FIELD(get_forums, forums, id);
FROM(get_forums, forums);
WHERE
VALUE_CONDITION(get_forums, forums, subscribed, C_EQUAL);
это код на дефайнах, который я максимально приближаю к sql синтаксису. Подразумевается что сия штука будет обрабатываться при запуске приложения, реструктуризировать бд если надо и генерировать sql запросы к базе, складывая их в map<имя, запрос>, а далее при работе достаточно будет прикрутить параметры к запросу и отправить на исполнение.
Вот.
Со стороны дб-модуля это выглядит приблизительно так:
void CPostgreEngine::checkDatabases(const db::objmodel::CDBMDatabaseDefinition *db)
{
db::objmodel::CDBMTable *table;
db::objmodel::CDBMDBField *field;
db::objmodel::CDBMIndex *index;
QString ddl;
foreach(table, db->getTables())
{
logger->Append(tr("Checking table %1").arg(table->getName()));
if (!itemExists(table->getName()))
{
exec("CREATE TABLE " + table->getName() + "();");
}
foreach(field, table->getFields())
{
if (!itemExists(field->getName(), table->getName(), plugins::base::edbField))
{
ddl += "ALTER TABLE " + table->getName() + " ADD COLUMN " + field->getName();
switch (field->getType())
{
case db::objmodel::ftInteger: ddl += " integer"; break;
case db::objmodel::ftString : ddl += QString(" varchar(%1)").arg(field->getStringFieldLength()); break;
case db::objmodel::ftBlob : ddl += " bytea"; break;
case db::objmodel::ftBool : ddl += " bool"; break;
}
if (field->isUnique()) {
ddl += " UNIQUE"; }
if (field->isNotNull()) {
ddl += " NOT NULL"; }
if (field->hasDefaultValue()) {
ddl += " DEFAULT '" + field->getDefaultValue().toString() + "'"; }
exec(ddl + ";");
ddl.clear();
}
}
if (!itemExists(table->getPrimaryKey()->getName(), table->getName(), plugins::base::edbPrimaryKey))
{
exec("ALTER TABLE " + table->getName() + " ADD CONSTRAINT " + table->getPrimaryKey()->getName() + " PRIMARY KEY (" + table->getPrimaryKey()->getFieldsNames(",") + ");");
}
foreach(index, table->getIndexes())
{
if (!itemExists(index->getName(), table->getName(), plugins::base::edbIndex))
{
exec("CREATE INDEX " + index->getName() + " ON " + table->getName() + " (" + index->getFieldsNames(",") + ");");
}
}
}
}
//----------------------------
QString CPostgreEngine::buildSelectQuery(db::objmodel::CDBMQuery *query)
{
db::objmodel::CDBMQueryField *field;
QString queryText = "SELECT ";
foreach(field, query->getFields())
{
switch(field->getSpecialType())
{
case db::objmodel::sftNone: queryText += field->getLinkedField()->getFullName() + ","; break; // not special, standart field
case db::objmodel::sftAll: queryText += "*,"; break; // *
case db::objmodel::sftCount: queryText += QString("count(%1) as %2,").arg(field->getLinkedField()->getFullName()).arg(field->getName()); break; // count(table.field) as f
case db::objmodel::sftSumm: queryText += QString("summ(%1) as %2,").arg(field->getLinkedField()->getFullName()).arg(field->getName()); break; // summ(table.field) as f
case db::objmodel::sftMax: queryText += QString("max(%1) as %2,").arg(field->getLinkedField()->getFullName()).arg(field->getName()); break; // max(table.field) as f
case db::objmodel::sftMin: queryText += QString("min(%1) as %2,").arg(field->getLinkedField()->getFullName()).arg(field->getName()); break; // min(table.field) as f
case db::objmodel::sftSimple: queryText += QString("\"%1\" as %2,").arg(field->getPresetValue()).arg(field->getName()) ; break; // "text" as f
}
}
queryText.resize(queryText.length() - 1);
queryText += " FROM " + query->getTablesNames();
if (!query->conditionsIsEmpty()) {
queryText += buildConditions(query->getConditions()); }
return queryText;
}