Есть запрос в базу данных, по ответу поддержки "классы 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 для выборки необходимого количества записей в запросе?

Нравится

8 комментариев
Лучший ответ

Проверил, на запросе с 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 &lt;= 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)

"

Проверил без TOP - такой ошибки нет

А если без этой колонки?

    .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 &lt;= 2)

Кстати, месяц назад Вы уже об этом спрашивали и я предлагал начать с выяснения мешающей колонки.

Зверев Александр,

 да, именно Ваша рекомендация с .As("SomeString") помогла когда прописал данный алиас во все колонки где используется "Column.Parameter". Так же в поддержке ответили. Не понял только почему в PostgreSQL это работает без алиаса, а в Oracle без него не так. Но видимо это специфика запросов СУБД, главное что с алиасом работает и там, и там.

Спасибо за помощь!

Передал информацию об этой особенности для освещения в академии.

Показать все комментарии

Приветы,

 

Подскажите плиз, как правильно сделать, создал объект наследуемый от базового и добавил поле BpCandidate как строка 50 символов в конструкторе объекта.

 

Пробовал сделать поле типа справочник и тогда оно становится Guid в коде

В следующем коде было вместо TEXT, у поля BpCandidate указан GUID

Так вот в консоли хрома видел ошибку уровня c#, а именно System.String не могу преобразовать в System.Guid и как быть? 

 

Удалив столбец, пересохранив и добавив его снова как строка 50 символов и вернув ТЕКСТ вместо ГУИД все заработало, но как быть с гуидами в инсерт запросами???

 

insertCount: function (candId) {

                this.logStep('insertCount started...');

                var insertQuery = this.Ext.create("Terrasoft.InsertQuery", {

                    rootSchemaName: "BpCandidateCall"

                });

                insertQuery.setParameterValue("CallCount",

                    1,

                    this.Terrasoft.DataValueType.INTEGER);



                insertQuery.setParameterValue("BpCandidate",

                    candId,

                    this.Terrasoft.DataValueType.TEXT);

                var dt = new Date();

                insertQuery.setParameterValue("CallDate",

                    dt,

                    this.Terrasoft.DataValueType.DATE);

                insertQuery.setParameterValue("CallTime",

                    dt,

                    this.Terrasoft.DataValueType.TIME);

                insertQuery.execute(function () {

                    //this.loadActivities();

                }, this);

                this.logStep('insertCount finished...');

            },

Нравится

1 комментарий

А что если колонка в базе будет GUID, а в коде выше DataValueType.TEXT?

Показать все комментарии

Уважаемые форумчане, подскажите пожалуйста...столкнулся с проблемой:
Для копирования прав доступа создал isq_CopyRight
Но выдает следующую ошибку: "Operand type clash: int is incompatible with uniqueidentifier", никак не могу разобраться. Опыта крайне мало, поэтому прошу помощи у профессионалов.

isq_CopyRight

INSERT INTO [dbo].[tbl_CashflowRight] ([ID], [RecordID], [AdminUnitID], [CanRead], [CanWrite], [CanDelete], [CanChangeAccess])
SELECT
        [tbl_CashflowRight].[CanRead] AS [CanRead],
        [tbl_CashflowRight].[CanWrite] AS [CanWrite],
        [tbl_CashflowRight].[CanDelete] AS [CanDelete],
        [tbl_CashflowRight].[CanChangeAccess] AS [CanChangeAccess],
        :OldRecordID AS [NewRecordID],
        :MyAdminUnitID AS [AdminUnitID],
        [tbl_CashflowRight].[ID] AS [ID]
FROM
        [dbo].[tbl_CashflowRight] AS [tbl_CashflowRight]
WHERE([tbl_CashflowRight].[RecordID] = :OldRecordID AND
        [tbl_CashflowRight].[AdminUnitID] = :MyAdminUnitID)

function CopyRight:

function CopyRight(OldRecordID, NewRecordID) {
        var InsertSelectQuery = GetSingleItemByCode('isq_CopyRight');
        var Columns = InsertSelectQuery.SelectQuery.Columns;
        var ConstColumn = Columns.ItemsByAlias('NewRecordID');
                ConstColumn.ColumnValue = NewRecordID;
        SetParameterValue(InsertSelectQuery.Parameters, 'OldRecordID', OldRecordID);
        SetParameterValue(InsertSelectQuery.Parameters, 'MyAdminUnitID',
        Connector.CurrentUser.ID);
                try {
        InsertSelectQuery.Execute();
        }
        catch(e) {
        CatchException(e);
        }
        }            

Нравится

4 комментария

Добрый день Дмитрий!!!

ваш запрос выглядит неверно. Вот правильный запрос на копирования прав:

INSERT INTO [dbo].[tbl_CashflowRight] ([ID], [RecordID], [AdminUnitID], [CanRead], [CanWrite], [CanDelete], [CanChangeAccess]) 
SELECT
        [tbl_CashflowRight].[ID] AS [ID],
        :OldRecordID AS [RecordID],
        :MyAdminUnitID AS [AdminUnitID],
        [tbl_CashflowRight].[CanRead] AS [CanRead],
        [tbl_CashflowRight].[CanWrite] AS [CanWrite],
        [tbl_CashflowRight].[CanDelete] AS [CanDelete],
        [tbl_CashflowRight].[CanChangeAccess] AS [CanChangeAccess]
FROM
        [dbo].[tbl_CashflowRight] AS [tbl_CashflowRight]
WHERE([tbl_CashflowRight].[RecordID] = :OldRecordID AND
        [tbl_CashflowRight].[AdminUnitID] = :MyAdminUnitID)

у вас Дмитрий поля в SELECT местами перепутаны. Порядок должен соответствовать порядку вставляемых полей

Спасибо большое!
Сейчас попробую :smile:

Ошибки не возникло, однако копирование прав не произошло :(
Не подскажете, где я мог еще ошибиться?

Дмитрий в Profiler SQL сервера выполните трассировку и посмотрите какой запрос формирует приложение к серверу. Вручную его исполните и увидите почему у вас непроизошла вставка новых данных.

Показать все комментарии