Продолжение темы: https://community.terrasoft.ru/questions/vopros-po-updateselect-k-razra…

 

Зачем в классе Terrasoft.DB.PostgreSql.PostgreSqlEngine в методе BuildUpdateSelectTargetSqlText(StringBuilder sb, ModifyQuerySource modifySource, string alias) код "string value = " \"" + alias + "\""; sb.Append(value);" ?

Класс генерирует неправильный запрос в БД:

var us =
	new UpdateSelect(_userConnection, "Contact", "c")
		.Set("Name", Column.Parameter("Andrew Baker (sample) + 1"))
		.From("Contact", "c")
		.InnerJoin("Account").As("a").On("a", "Id").IsEqual("c", "AccountId")
		.Where("a", "Web").IsEqual(Column.Parameter("ac.com"))
		.And("c", "Id").IsNotEqual(Column.Parameter(Guid.NewGuid()))
	as UpdateSelect;
UPDATE "public"."Contact" "c"
SET
	"Name" = 'Andrew Baker (sample) + 1'
FROM
	"public"."Contact" "c"
	INNER JOIN "public"."Account" "a" ON "a"."Id" = "c"."AccountId"
WHERE
	"a"."Web" = 'ac.com'
	AND "c"."Id" <> '{19812101-C7A9-4DED-BD44-F8973A98D746}'

Результат выполнения:

Изображение удалено.

При этом если бы упомянутого выше кода не было, то запрос был бы верным:

Изображение удалено.

Нравится

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

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

var us =

                new UpdateSelect(UserConnection, "Contact", "c")

                    .Set("Name", Column.Parameter("Andrew Baker (sample) + 2"))

                    .From("Contact", "ca")

                    .InnerJoin("Account").As("a").On("a", "Id").IsEqual("ca", "AccountId")

                    .Where("a", "Web").IsEqual(Column.Parameter("ac.com"))

                    .And("ca", "Id").IsNotEqual(Column.Parameter(Guid.NewGuid()))

                as UpdateSelect;

Как и в случае с методом ReplaceUpdateTargetAliasWithName, эта строка нужна для правильного построения запроса. С ней были проведены тесты и они показали правильность её работы.

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

Зачем в классе Terrasoft.DB.MSSql.MSSqlEngine в методе BuildConditionSqlText(StringBuilder sb, UpdateSelect query) вызов метода ReplaceUpdateTargetAliasWithName(QueryCondition condition, string alias, string name) ?

 

Класс генерирует неправильный запрос в БД:

var us =
	new UpdateSelect(_userConnection, "Contact", "c")
		.Set("Name", Column.Parameter("Andrew Baker (sample) + 1"))
		.From("Contact", "c")
		.InnerJoin("Account").As("a").On("a", "Id").IsEqual("c", "AccountId")
		.Where("a", "Web").IsEqual(Column.Parameter("ac.com"))
		.And("c", "Id").IsNotEqual(Column.Parameter(Guid.NewGuid()))
	as UpdateSelect;

 

UPDATE [dbo].[Contact]
SET
        [Name] = N'Andrew Baker (sample) + 1'
FROM
        [dbo].[Contact] [c]
        INNER JOIN [dbo].[Account] [a] ON ([a].[Id] = [c].[AccountId])
WHERE
        [a].[Web] = N'ac.com'
        AND [Contact].[Id] <> '{19812101-C7A9-4DED-BD44-F8973A98D746}'

Результат выполнения:

Изображение удалено.

При этом если бы упомянутый выше метод не вызывался, то запрос был бы верным:

Изображение удалено.

Нравится

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

Владислав, добрый день!

Прошу уточнить, при каких условиях у вас генерируется этот запрос?

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

var us =

                new UpdateSelect(UserConnection, "Contact", "c")

                    .Set("Name", Column.Parameter("Andrew Baker (sample) + 2"))

                    .From("Contact", "ca")

                    .InnerJoin("Account").As("a").On("a", "Id").IsEqual("ca", "AccountId")

                    .Where("a", "Web").IsEqual(Column.Parameter("ac.com"))

                    .And("ca", "Id").IsNotEqual(Column.Parameter(Guid.NewGuid()))

                as UpdateSelect;

Сам метод ReplaceUpdateTargetAliasWithName добавлен не просто так, он необходим для правильного построения запросов.

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

Нужно реализовать обновление данных с помощью класса UpdateSelect. Но не работает группировка условий.

UPDATE [dbo].[TestTbl]
SET [val2] = [source].[val2]
FROM [dbo].[TestTbl2] [source]
WHERE ([source].[id] = [TestTbl].[id] OR [source].[id2] = [TestTbl].[id2]) AND
	([source].[id3] = [TestTbl].[id3] OR [source].[id4] = [TestTbl].[id4])

При формировании аналогичного запроса для выборки (Select) - все работает корректно.

Изображение удалено.

При исследовании ошибки было выявлено, что ошибка возникает во внутренней логике в dll Terrasoft.Core.MSSql, так как группа методов .Where().OpenBlock() в коллекции условий запроса создала пустой QueryCondition, а в dll нет проверки на возможность пустого условия.

Изображение удалено.

Изображение удалено.



Мое предположение: непредвиденный кейс в dll.

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

Владислав, а зачем делать блок с одним условием? Обычно блоки делают, чтобы внутри or и снаружи and или наоборот. Пример, но только Select, есть тут.

Если сделать полноценный блок, тоже Update будет с ошибкой?

И, если не затруднит, приложите код текстом, а не скриншотами.

Зверев Александр пишет:

Владислав, а зачем делать блок с одним условием? Обычно блоки делают, чтобы внутри or и снаружи and или наоборот. Пример, но только Select, есть тут.

Если сделать полноценный блок, тоже Update будет с ошибкой?

И, если не затруднит, приложите код текстом, а не скриншотами.

Одно условие для простоты понимания ошибки. Изначально было несколько условий, как в приложеном SQL. Но даже такая ситуация возможна. Вот я просто хочу обернуть одно условие в скобки. 

Здесь проблема именно в классе UpdateSelect, другие классы (Select, Update) работают нормально с такими условиями.

Предоставленный метод из базовой dll вызывается только для UpdateSelect и в методе нет проверки.

 

var select1 =
    new Select(_userConnection)
    .Column("source", "id")
    .Column("source", "val2")
    .From("TestTbl2", "source")
    .Where("source", "id").IsEqual("TestTbl", "id");
 
Console.WriteLine(select1.GetSqlText());
Console.WriteLine("----------------------------------------------------");
 
var select2 =
    new Select(_userConnection)
    .Column("source", "id")
    .Column("source", "val2")
    .From("TestTbl2", "source")
    .Where().OpenBlock("source", "id").IsEqual("TestTbl", "id").CloseBlock();
 
Console.WriteLine(select2.GetSqlText());
Console.WriteLine("----------------------------------------------------");
 
var update1 =
    new UpdateSelect(_userConnection, "TestTbl", "TestTbl")
    .Set("val2", Column.SourceColumn("source", "val2"))
    .From("TestTbl2", "source")
    .Where("source", "id").IsEqual("TestTbl", "id");
 
Console.WriteLine(update1.GetSqlText());
Console.WriteLine("----------------------------------------------------");
 
var update2 =
    new UpdateSelect(_userConnection, "TestTbl", "TestTbl")
    .Set("val2", Column.SourceColumn("source", "val2"))
    .From("TestTbl2", "source")
    .Where().OpenBlock("source", "id").IsEqual("TestTbl", "id").CloseBlock();
 
Console.WriteLine(update2.GetSqlText());

 

 

Стоит добавить простую проверку:

Ошибку обнаружили, разработчики занимаются ее решением. 

В качестве обходного решения необходимо использовать Select и Update отдельно.

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