Здравствуйте, Sinclair, Вы писали:
S>Или вообще вот так: S>
S>select o.*, o.Owner.Name from orders o
S>
S>Т.е. употребление конструкции o.Owner автоматически приджойнивает таблицу, указанную в соответствующем FK.
Будешь смеяться, но именно так сделано в HQL (Hibernate Query Language). Это одна из фич, которая делает запросы с тремя-четырьмя уровнями join'ов читабельными.
Мне кажется проблему декомпозиции можно было бы решить куда проще. Надо было просто добавить возможность задания переменных. Причем, чтобы не ломать декларативный дух SQL-я, они должны быть (как в ФЯ) доступны только для чтения. Если еще добавить возможность описания фунций и оператор if (но с семантикой как у опертора ?: в С), то проблем с декомпозицией не было бы. В прочем, фунции наверно это и есть более математическо (что ли) название для параметрезованных вьюх. В общем, нужно брать классику. ФП тут подошло бы на ура.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Sinclair, Вы писали:
VD>Мне кажется проблему декомпозиции можно было бы решить куда проще. Надо было просто добавить возможность задания переменных. Причем, чтобы не ломать декларативный дух SQL-я, они должны быть (как в ФЯ) доступны только для чтения.
А какой тип будет у этой переменной?
Можно же делать примерно так:
create viewallCustomers#as ...
GO
select * fromallCustomers# a1 joinallCustomers# a2 on ...
VD> Если еще добавить возможность описания фунций и оператор if (но с семантикой как у опертора ?: в С), то проблем с декомпозицией не было бы. В прочем, фунции наверно это и есть более математическо (что ли) название для параметрезованных вьюх. В общем, нужно брать классику. ФП тут подошло бы на ура.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, VladD2, Вы писали:
VD>>Здравствуйте, Sinclair, Вы писали:
VD>>Мне кажется проблему декомпозиции можно было бы решить куда проще. Надо было просто добавить возможность задания переменных. Причем, чтобы не ломать декларативный дух SQL-я, они должны быть (как в ФЯ) доступны только для чтения. S>А какой тип будет у этой переменной?
Полиморфный, с ограничением общности. В твоем примере
create view InProgress(TaskTable @tablename) as
select * from @tableName where status in ("open", "assigned", "verifying")
@tablename должна выставлять интерфейс HasField status (ну синтаксис какой-то другой, понятно). Тут он, кстати, из применения выводится.
VD>Мне кажется проблему декомпозиции можно было бы решить куда проще. Надо было просто добавить возможность задания переменных. Причем, чтобы не ломать декларативный дух SQL-я, они должны быть (как в ФЯ) доступны только для чтения. Если еще добавить возможность описания фунций и оператор if (но с семантикой как у опертора ?: в С), то проблем с декомпозицией не было бы. В прочем, фунции наверно это и есть более математическо (что ли) название для параметрезованных вьюх. В общем, нужно брать классику. ФП тут подошло бы на ура.
Вообще уже давно есть: курсоры, в оракле ещё есть pipelined functions, и if есть, только немного с другой семантикой. Главная проблема, что в нынешнем виде это всё жутко неудобно, недостаточно по функциональности и неунифицировано (в смысле нестандартно).
Здравствуйте, VladD2, Вы писали:
VD>Мне кажется проблему декомпозиции можно было бы решить куда проще. Надо было просто добавить возможность задания переменных. Причем, чтобы не ломать декларативный дух SQL-я, они должны быть (как в ФЯ) доступны только для чтения. Если еще добавить возможность описания фунций и оператор if (но с семантикой как у опертора ?: в С), то проблем с декомпозицией не было бы. В прочем, фунции наверно это и есть более математическо (что ли) название для параметрезованных вьюх. В общем, нужно брать классику. ФП тут подошло бы на ура.
Оператор if "с семантикой опертора ?: в С" в SQL есть. Большинство современных диалектов позволяют делать подзапросы (это то, что ты назвал "функции"). Это принципиальный функционал. А объявления /неизменяемых/ переменных и декларация функций это банальный синтаксический сахар Т.е. нужно только для слабых духом
Здравствуйте, Sinclair, Вы писали:
S>1. Главное препятствие декомпозиции — отсутствие в стандарте параметризованных view. В итоге, вместо того, чтобы легким манием руки приджойнить EmployeeOrders(Name) мы пишем join EmployeeOrders where EmployeeName = Name.
А функции чем не подходят?
S>2. Второе препятствие декомпозиции — отсутствие в стандарте способа задания открытых view. В итоге совершенно невозможно написать ничего подобного этому: S>
S>create view InProgress(TaskTable @tablename) as
S>select * from @tableName where status in ("open", "assigned", "verifying")
S>
S>И применять ко всем подходящим таблицам.
В MSSQL 2008 вроде бы подобное есть, но насчет эффективности ХЗ.
S>3. Невозможность использовать алиасы для скалярных выражений. В order by можно хотя бы указать цифру, но в остальных местах приходится честно переписывать все нужные выражения.
Т.е. нужно что то типа let в LINQ?
S>4. Жутко многословный синтаксис джойнов. Нет, я понимаю всю красоту идеи, но 99% джойнов — это equality join по foreign key. Синтаксис этого никак не отражает. Поддержка упрощенного синтаксиса FK-джойнов была бы офигенным улучшением, сокращающим большинство запросов на порядок. Примерно так: S>Или вообще вот так: S>
S>select o.*, o.Owner.Name from orders o
S>
S>Т.е. употребление конструкции o.Owner автоматически приджойнивает таблицу, указанную в соответствующем FK.
Это в нашем DSL тоже есть, собственно идея на поверхности лежит. Но тут есть засада в том случае, если FK допускает null. Нормально разресолвить это можно только при помощи статического null-анализа и выкидывания исключения, если возможно обращение по null.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали: AVK>А функции чем не подходят?
Нестандартностью. S>>И применять ко всем подходящим таблицам.
AVK>В MSSQL 2008 вроде бы подобное есть, но насчет эффективности ХЗ.
Эффективность всего этого должна быть нормальной, потому что в итоге все равно получается некий "плоский" запрос, который уходит к оптимизатору. AVK>Т.е. нужно что то типа let в LINQ?
Типа того. Хотя я бы предпочел сам Linq Я имею в виду всякие бодрые трансформации запроса на ходу. А то меня (и оптимизатор) со страшной силой бесят все эти
where ((@startDate is null) or (orderDate>@startDate)
S>>Т.е. употребление конструкции o.Owner автоматически приджойнивает таблицу, указанную в соответствующем FK.
AVK>Это в нашем DSL тоже есть, собственно идея на поверхности лежит. Но тут есть засада в том случае, если FK допускает null.
Да, тут проблема, т.к. непонятно, outer или inner join имел в виду программист. Скорее всего таки outer, т.к. при inner строчки с FK в null будут таинственным образом пропадать. AVK>Нормально разресолвить это можно только при помощи статического null-анализа и выкидывания исключения, если возможно обращение по null.
Вот тут я не понимаю. Зачем чего-то статически резолвить?
Это же сахар:
select o.*, Owner.Name from orders o
outer join Employee on Employee.ID = Order.EmployeeID
тут же не будет никаких исключений, верно? Точно так же будет себя вести и Owner.Address.Name в случае более длинных штук. Отрулить обратно к иннеру всегда можно дополнением
where Owner is not null
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
AVK>>А функции чем не подходят? S>Нестандартностью.
Их разве в sql'03 нет?
AVK>>В MSSQL 2008 вроде бы подобное есть, но насчет эффективности ХЗ. S>Эффективность всего этого должна быть нормальной, потому что в итоге все равно получается некий "плоский" запрос, который уходит к оптимизатору.
Не факт.
AVK>>Т.е. нужно что то типа let в LINQ? S>Типа того.
+1
S> Хотя я бы предпочел сам Linq Я имею в виду всякие бодрые трансформации запроса на ходу. А то меня (и оптимизатор) со страшной силой бесят все эти S>
S>where ((@startDate is null) or (orderDate>@startDate)
S>
Ну, это уже не столько к SQL вопросы, сколько вообще к архитектуре сегодняшних РСУБД
AVK>>Это в нашем DSL тоже есть, собственно идея на поверхности лежит. Но тут есть засада в том случае, если FK допускает null. S>Да, тут проблема, т.к. непонятно, outer или inner join имел в виду программист.
Именно. Причем в некоторых случаях он мог ене иметь ни того. ни другого, а скорее даже выдачу ошибки, если там реально где то null попался.
S> Скорее всего таки outer, т.к. при inner строчки с FK в null будут таинственным образом пропадать.
Ну вот я пока у себя сделал outer, но результат при этом тоже не особо очевидным получается
AVK>>Нормально разресолвить это можно только при помощи статического null-анализа и выкидывания исключения, если возможно обращение по null. S>Вот тут я не понимаю. Зачем чего-то статически резолвить? S>Это же сахар: S>
S>select o.*, Owner.Name from orders o
S>outer join Employee on Employee.ID = Order.EmployeeID
S>
S>тут же не будет никаких исключений, верно?
Да, но здесь мы явно показываем семантику того, что хотим увидеть. А выражение Owner.Name предполагает все таки обязательное наличие Owner, иначе семантика получается бредовой. Можно было бы просто при попытке использовать такое по FK без NOT NULL ругаццо, но остается ситуация вроде:
select Owner.Name from orders where Owner is not null
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали: AVK>Их разве в sql'03 нет? Я че-то не проследил. Так что может быть претензию можно и снять.
S>> Хотя я бы предпочел сам Linq Я имею в виду всякие бодрые трансформации запроса на ходу. А то меня (и оптимизатор) со страшной силой бесят все эти S>>
S>>where ((@startDate is null) or (orderDate>@startDate)
S>>
AVK>Ну, это уже не столько к SQL вопросы, сколько вообще к архитектуре сегодняшних РСУБД
Не-не-не. Это к тому, что запрос строится слишком жестким образом. С ним можно работать только как с целым. Хотя... Если будут переменные типа "SQL запрос", которые дешево создавать и модифицировать, то как раз можно добиться многого. Типа
if @startDate is not null
then
define aas
select * fromawhere orderDate>@startDate
AVK>Именно. Причем в некоторых случаях он мог ене иметь ни того. ни другого, а скорее даже выдачу ошибки, если там реально где то null попался.
Ну, это уже что-то из области не-РСУБД. Вся семантика аутер джойнов для нормального человека малопонятна.
AVK>Да, но здесь мы явно показываем семантику того, что хотим увидеть. А выражение Owner.Name предполагает все таки обязательное наличие Owner, иначе семантика получается бредовой. Можно было бы просто при попытке использовать такое по FK без NOT NULL ругаццо, но остается ситуация вроде: AVK>
AVK>select Owner.Name from orders where Owner is not null
AVK>
Можно покопать в сторону чего-то типа operator lifting в C# 2.0. Я имею в виду, что семантика Owner.Name может быть и такой: (Owner == null ? Owner.Name : (string?) null).
Можно оставить выброс исключения, а предложенное поведение повесить на что-то кроме точки. Ну там типа ?.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
AVK>>Их разве в sql'03 нет? S> Я че-то не проследил. Так что может быть претензию можно и снять.
Ну, мои познания в деталях ограничиваются sql'92 и немножко sql'99
AVK>>Ну, это уже не столько к SQL вопросы, сколько вообще к архитектуре сегодняшних РСУБД S>Не-не-не. Это к тому, что запрос строится слишком жестким образом. С ним можно работать только как с целым. Хотя... Если будут переменные типа "SQL запрос", которые дешево создавать и модифицировать, то как раз можно добиться многого. Типа S>
S>if @startDate is not null
S>then
S> define aas
S> select * fromawhere orderDate>@startDate
S>
Это уже ближе к императивным расширениям SQL, т.е. совсем другой разговор. В этом случаем можно спокойно пользовать C# совместно с SQL-CLR, в том числе и с Linq2Sql.
S>Ну, это уже что-то из области не-РСУБД. Вся семантика аутер джойнов для нормального человека малопонятна.
Отнюдь. Ты сейчас представляешь себе это ввиде джойна. Однако это не правомерно, это отдельная конструкция языка. И семантику ее надо делать не исходя из того, что это джойн, а исключительно с точки зрения собственной конструкции. А с этой точки зрения поведение, аналогичное outer join является крайне неочевидным. А РСУБД это, или не РСУБД, это уже второй вопрос, реляционная алгебра не идол, на нее давно уже никто не молется.
S>Можно покопать в сторону чего-то типа operator lifting в C# 2.0. Я имею в виду, что семантика Owner.Name может быть и такой: (Owner == null ? Owner.Name : (string?) null).
Неочевидно. Особенно если это какой нибудь Owner.Person.Address.City.Name.
S>Можно оставить выброс исключения, а предложенное поведение повесить на что-то кроме точки. Ну там типа ?.
А каков физический смысл подобного поведения (которое идентично outer join)?
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
def query1 = select * from customers where <some conditions>
def query2(x, y) = select ... fromquery1where someTable.x = x and someTable.y = y
select query2(123, "yes")
В общем, главная мысль в том, что разные T-SQL и P-SQL пошли по неверному пути. Они расширяют красивый деларатив SQL императивными конструкциями, причем в кривешем исполнении. Вместо этого можно было снабдив SQL всего тремя фичами сделать красиво решение позволяющее решать не только проблему декомпозиции сложных запросов, но и делающее SQL полным по Тьюренгу языком.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>В общем, главная мысль в том, что разные T-SQL и P-SQL пошли по неверному пути. Они расширяют красивый деларатив SQL императивными конструкциями, причем в кривешем исполнении. Вместо этого можно было снабдив SQL всего тремя фичами сделать красиво решение позволяющее решать не только проблему декомпозиции сложных запросов, но и делающее SQL полным по Тьюренгу языком.
Правильно, без боли на ужаснейшие бейсик-like выражения из PlSQL смотреть нельзя. Лучше расширять его через функцинальные фичи. Пример — Q.
VD>def query1 = select * from customers where <some conditions>
VD>def query2(x, y) = select ... fromquery1where someTable.x = x and someTable.y = y
VD>select query2(123, "yes")
VD>
А чем не нравится оператор WITH (в MSSQL 2005) и WITH (в Oracle)? У него вижу проблему только в том, что WITH работает только для одного запроса, т.е. упростит только один запрос.
VD>В общем, главная мысль в том, что разные T-SQL и P-SQL пошли по неверному пути. Они расширяют красивый деларатив SQL императивными конструкциями, причем в кривешем исполнении. Вместо этого можно было снабдив SQL всего тремя фичами сделать красиво решение позволяющее решать не только проблему декомпозиции сложных запросов, но и делающее SQL полным по Тьюренгу языком.
В общем виде в MS SQL есть средство, что пользовательская функция может возвращать результат запроса и принимать параметры для него, что является мощной заменой вьюхам. (В оракле такого нет, вроде, можно только курсор возвращать ) Единственно возникает вопрос — а на сколько это хорошая замена вьюхам и вложенным запросам?
на счет IF:
WITH EXPR AS
(SELECT/*ТУТ УСЛОВИЕ*/FROM DUAL)
select * from EXPR e, TABLE_1 where e.result = 0
union all
select * from EXPR e, TABLE_2 where e.result <> 0
или даже заинлайнить условие...
но, по моей практике, такое встречается не часто...
Здравствуйте, Plague, Вы писали:
P>Единственно возникает вопрос — а на сколько это хорошая замена вьюхам и вложенным запросам?
Если говорить об inline-функциях — прекрасное. Единственная дырка — нет сущности между глобальной функцией и локальным CTE. Да и CTE, ИМХО, синтаксически не очень удачно.
... << RSDN@Home 1.2.0 alpha rev. 725 on Windows Vista 6.0.6000.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Plague, Вы писали:
P>>Единственно возникает вопрос — а на сколько это хорошая замена вьюхам и вложенным запросам?
AVK>Если говорить об inline-функциях — прекрасное. Единственная дырка — нет сущности между глобальной функцией и локальным CTE. Да и CTE, ИМХО, синтаксически не очень удачно.
Да, к сожалению... В Оракле есть пакеты, что сильно уменьшает количество "видимых" процедур, да и так в Оракле можно создавать вложенные процедуры.
Но вот, что нет подобных функций, что возвращают Таблицы, как парамтризированные вьюхи...
Здравствуйте, Plague, Вы писали:
P>А чем не нравится оператор WITH (в MSSQL 2005) и WITH (в Oracle)? У него вижу проблему только в том, что WITH работает только для одного запроса, т.е. упростит только один запрос.
1. Это хреново выглядит и читается.
2. Это не стандартные расширения.
3. У Оракла нельзя зада параметры.
4. По уму функцию должно быть можно задать как локально (для пакета запросов), так и на уровне БД, так чтобы ее можно было использовать многкратно. Собственно второе тоже кое как реализовано во многих серверах, но опять же через зад автогеном и опять же это нестандартные расширения.
P>В общем виде в MS SQL есть средство, что пользовательская функция может возвращать результат запроса и принимать параметры для него,
MS SQL это частное решение, а речь идет о SQL как о стандарте.
К тому же MS SQL имеет массу других кривых решений появившихся сильно раньше и массу ограничений.
P> что является мощной заменой вьюхам. (В оракле такого нет, вроде, можно только курсор возвращать ) Единственно возникает вопрос — а на сколько это хорошая замена вьюхам и вложенным запросам?
Это не замена вложенным запросам, а средство декомпозиции. Вьюхи, на мой взгляд, это недоразумение. Они аналогичны функциям возвращающим результат запроса, но без параметров.
Если бы в начале проектирования SQL-ы ввели бы синтаксис immutable-присвоения, фунции и if, то нужны в большинстве примочек, появившихся за эти годы в диалектах SQL-я, попросту не поднадобилось бы. Те же вьюхи были бы банальным частным случаем.
P>на счет IF: P>
P>WITH EXPR AS
P>(SELECT/*ТУТ УСЛОВИЕ*/FROM DUAL)
P>select * from EXPR e, TABLE_1 where e.result = 0
P>union all
P>select * from EXPR e, TABLE_2 where e.result <> 0
P>
P>или даже заинлайнить условие...
P>но, по моей практике, такое встречается не часто...
Кривотень какая-то. Аналоги ифу конечно есть. Я не пойму зачем надо было делать все раком?
В прочем, я рассуждаю сейчас, когда есть масса научных наработок в области языкостроения, а тогда все это было изобретательство.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VGn, Вы писали:
VGn>Вообще уже давно есть: курсоры, в оракле ещё есть pipelined functions, и if есть, только немного с другой семантикой.
Ага. Если бы не было этих только и было бы это все не в Оракле, а в стандарте SQL. То было бы хорошо.
Курсоры это худшее что можно было придумать. Другой if тоже не катит.
VGn> Главная проблема, что в нынешнем виде это всё жутко неудобно, недостаточно по функциональности и неунифицировано (в смысле нестандартно).
Дык. О том и речь. А могло бы быть просто и фунционально. Просто люди что развивали SQL, развивали его по наитию. Они просто не знали, что то чем они занимаются сто раз проработано до них. Вот и нагородили монструзных колсов на глинянных ногах вроде T-SQL и PSQL.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.