Есть запрос в базу данных, по ответу поддержки "классы EntitySchemaQuery, Select, Insert, Update, Delete это СУБД-независимое API ", исходя из этого был использован InsertSelect. На PostgreSQL запрос отрабатывает отлично, но в Oracle выдает ошибку при использовании TOP в запросе.
Код запроса:
Query selectQuery = new Select(UserConnection) .Top(numberCountForNumberPool) .Column(Column.Parameter(request)) .Column(Column.Parameter(currentUserContactId)) .Column(Column.Parameter(currentUserContactId)) .Column("KtSimManagementInitialPoolNumbers", "KtIccid") .Column("KtSimManagementInitialPoolNumbers", "KtImsi") .Column("KtSimManagementInitialPoolNumbers", "KtMsisdn") .Column("KtSimManagementInitialPoolNumbers", "KtName") .Column(Column.Parameter(cityAndCountNumbersEntity.GetTypedColumnValue<Guid>(city.Name))) .Column(Column.Parameter(cityAndCountNumbersEntity.GetTypedColumnValue<string>(note.Name))) .Column(Column.Parameter(DateTime.UtcNow.Date)) .Column(Column.Parameter(DateTime.UtcNow.Date .AddDays((int)Core.Configuration.SysSettings.GetValue(UserConnection, "DayCountForDedicatedPoolNumbers") + 1).AddSeconds(-1))) .From("KtSimManagementInitialPoolNumbers") .OrderByAsc("KtSimManagementInitialPoolNumbers", "KtName") .Join(JoinType.LeftOuter, "KtJasperFullNumberPool") .On("KtSimManagementInitialPoolNumbers", "KtName") .IsEqual("KtJasperFullNumberPool", "KtName") .Where("KtJasperFullNumberPool", "KtName") .IsNull() .And("KtSimManagementInitialPoolNumbers", "KtMarketCodeId") .IsEqual(Column.Parameter(cityForMarketCode)); InsertSelect insertSelectQuery = new InsertSelect(UserConnection) .Into("KtJasperFullNumberPool") .Set("KtRequestId", "ModifiedById", "CreatedById", "KtIccid", "KtImsi", "KtMsisdn", "KtName", "KtCityId", "KtNote", "KtReserveDate", "KtReserveToDate") .FromSelect(selectQuery); int numberCountInserted = insertSelectQuery.Execute();
Подскажите, есть ли возможность использовать в Select для Oracle - TOP для выборки необходимого количества записей в запросе?
Нравится
Проверил, на запросе с Top, OrderByAsc, Join, On, IsEqual, Where отрабатывает нормально. А если добавить колонки с числом и датой из параметра, получим такую же ошибку, как у Вас. Но если, как я выше предложил, дописать «.As», она исчезнет:
var query = new Select(UserConnection) .Top(2) .Column("Contact", "Dear") .Column(Column.Parameter("test")).As("SomeString") .Column(Column.Parameter(DateTime.UtcNow.Date)).As("SomeDate") .From("Contact") .OrderByAsc("Contact", "Dear") .Join(JoinType.LeftOuter, "Account") .On("Contact", "AccountId") .IsEqual("Account", "Id") .Where("Account", "AnnualRevenueId") .IsNull() ; var text = query.GetSqlText();
Код генерируется:
SELECT "Dear", "SomeString", "SomeDate"FROM (SELECT "Contact"."Dear", :P1 "SomeString", :P2 "SomeDate"FROM "название_базы"."Contact", "название_базы"."Account"WHERE ("Account"."AnnualRevenueId" IS NULL) AND "Contact"."AccountId" = "Account"."Id"(+)ORDER BY "Contact"."Dear" ASC NULLS FIRST)WHERE (ROWNUM <= 2)
Кстати, месяц назад Вы уже об этом спрашивали и я предлагал начать с выяснения мешающей колонки.
Александр, какая именно выдаётся ошибка? Только в Insert Select или просто в Select с Top тоже?
Если перед последней строчкой считать insertSelectQuery.GetSqlText(), что там будет?
Зверев Александр,
в Select тоже, пишет что "
Terrasoft.Common.NullOrEmptyException: Псевдоним колонки запроса не может быть пустым
в Terrasoft.Core.DB.DBEngine.BuildSelectColumnAliasesSqlText(StringBuilder sb, QueryColumnExpressionCollection columnExpressions)
в Terrasoft.DB.Oracle.OracleEngine.BuildSelectQuerySqlText(StringBuilder sb, Select select)
в Terrasoft.Core.DB.DBEngine.BuildQuerySqlText(StringBuilder sb, Select selectQuery)
в Terrasoft.Core.DB.DBEngine.GetQuerySqlText(Select selectQuery)
в Terrasoft.Core.DB.Select.GetSqlText()
в Terrasoft.Configuration.KtReserveNumbersService.ReserveNumbers(Guid request)
в SyncInvokeReserveNumbers(Object , Object[] , Object[] )
в System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
в Terrasoft.Web.Common.ServiceModel.ThreadContextInitializer.Invoke(Object instance, Object[] inputs, Object[]& outputs)
в System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
"
А если без этой колонки?
.Column(Column.Parameter(DateTime.UtcNow.Date .AddDays((int)Core.Configuration.SysSettings.GetValue(UserConnection, "DayCountForDedicatedPoolNumbers") + 1).AddSeconds(-1)))
Или с ней, но сразу после после дописать псевдоним:
.As("MyColumnName")
Она самая подозрительная, но если дело не в ней, проверьте и предыдущие.
Зверев Александр, Проверил - при закоментировании колонок разницы нет, но заметил закономерность:
1) если использовать Top без OrderByAsc и Join (ну вчесте с его on, IsEqual, Where) - тогда работает
2) если использовать OrderByAsc или Join (ну вчесте с его on, IsEqual, Where) без Top - тогда работает
3) если использовать Top с OrderByAsc или Join (ну вчесте с его on, IsEqual, Where) - тогда не работает, ошибка
Проверил, на запросе с Top, OrderByAsc, Join, On, IsEqual, Where отрабатывает нормально. А если добавить колонки с числом и датой из параметра, получим такую же ошибку, как у Вас. Но если, как я выше предложил, дописать «.As», она исчезнет:
var query = new Select(UserConnection) .Top(2) .Column("Contact", "Dear") .Column(Column.Parameter("test")).As("SomeString") .Column(Column.Parameter(DateTime.UtcNow.Date)).As("SomeDate") .From("Contact") .OrderByAsc("Contact", "Dear") .Join(JoinType.LeftOuter, "Account") .On("Contact", "AccountId") .IsEqual("Account", "Id") .Where("Account", "AnnualRevenueId") .IsNull() ; var text = query.GetSqlText();
Код генерируется:
SELECT "Dear", "SomeString", "SomeDate"FROM (SELECT "Contact"."Dear", :P1 "SomeString", :P2 "SomeDate"FROM "название_базы"."Contact", "название_базы"."Account"WHERE ("Account"."AnnualRevenueId" IS NULL) AND "Contact"."AccountId" = "Account"."Id"(+)ORDER BY "Contact"."Dear" ASC NULLS FIRST)WHERE (ROWNUM <= 2)
Кстати, месяц назад Вы уже об этом спрашивали и я предлагал начать с выяснения мешающей колонки.
Зверев Александр,
да, именно Ваша рекомендация с .As("SomeString") помогла когда прописал данный алиас во все колонки где используется "Column.Parameter". Так же в поддержке ответили. Не понял только почему в PostgreSQL это работает без алиаса, а в Oracle без него не так. Но видимо это специфика запросов СУБД, главное что с алиасом работает и там, и там.
Спасибо за помощь!
Передал информацию об этой особенности для освещения в академии.