Просьба помочь собрать такой запрос при помощи класса select

select count(ID)

   from [dbo].[Case] AS TI

WHERE DATEPART(HOUR, DATEADD(hh, 6, TI.[UsrDueDate])) >=9  and DATEPART(HOUR, DATEADD(hh, 6, TI.[UsrDueDate])) <12

and FORMAT(DATEADD(hh, 6, TI.[UsrDueDate]), N'yyyy.MM.dd') = FORMAT(cast(GETDATE() +1 as date), N'yyyy.MM.dd')

Заранее спасибооо! 

Нравится

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

Добрый день, Адилет.

 

Вы можете настроить SQL-представление (view) с нужным условием.

 

А потом из этого представления уже делать выборку с помощью класса select.

 

Или же попробовать сделать по аналогии с примерами запросов по этой ссылке.

Alla Savelieva,

Благодарю, будем пробовать.

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

Зачем в классе 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 добавлен не просто так, он необходим для правильного построения запросов.

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

Случилось так, что у меня слетело время на серверах. стал 2041 год. Исправили. 

Но вохник вопрос а что же с БД произошло? много ли записей с датой в будущем теперь у меня? Ответ - не много - около 1000, все исправил.

Но по ходу пьесы наткнулся на интересную вещь. Чисто логически в БД не должно быть записей с CratedOn или ModifiedOn > GETUTCDATE(). А они есть и не где либо, а в системных таблицах.

Для поиска своих записей из 2041 года набросал скрипт 

if  OBJECT_ID(N'tempdb..#Results') is not null
	Drop Table #Results
 
CREATE TABLE #Results (ColumnName nvarchar(370), Id uniqueidentifier)
 
SET NOCOUNT ON
 
DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
SET  @TableName = ''
WHILE @TableName IS NOT NULL
BEGIN
	SET @ColumnName = ''
	SET @TableName = 
	(
		SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
		FROM 	INFORMATION_SCHEMA.TABLES
		WHERE 		TABLE_TYPE = 'BASE TABLE'
			AND	QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
			AND	OBJECTPROPERTY(
					OBJECT_ID(
						QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
							), 'IsMSShipped'
						    ) = 0
	)
 
	WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
	BEGIN
 
		SET @ColumnName =
		(
			SELECT MIN(QUOTENAME(COLUMN_NAME))
			FROM 	INFORMATION_SCHEMA.COLUMNS
			WHERE 		TABLE_SCHEMA	= PARSENAME(@TableName, 2)
				AND	TABLE_NAME	= PARSENAME(@TableName, 1)
				AND	QUOTENAME(COLUMN_NAME) > @ColumnName
				And QUOTENAME(COLUMN_NAME) in ('[CreatedOn]', '[ModifiedOn]')
		)
		IF @ColumnName IS NOT NULL
		BEGIN
 
			INSERT INTO #Results
			EXEC
			(
				'SELECT ''' + @TableName + '.' + @ColumnName + ''', Id  
				FROM ' + @TableName + ' (NOLOCK) ' +
				' WHERE ' + @ColumnName + ' > GETUTCDATE() '
			)
		END
	END	
END
 
SELECT ColumnName, Id FROM #Results

После устранения 2041 года остались записи

ColumnName    Id

[dbo].[SysPackageSchemaData].[ModifiedOn]    2C172889-10E7-460D-A630-91E20CCC9ED8

[dbo].[SysPackageSqlScript].[ModifiedOn]    B2C17845-F2FD-43A9-97DF-946E2D74588C

[dbo].[SysProfileData].[ModifiedOn]    452EB96A-2F2D-4CDC-B244-823DEE7F36EA

[dbo].[SysProfileData].[ModifiedOn]    A46E427B-1514-478C-8F1E-A909B7D32B03

[dbo].[SysProfileData].[ModifiedOn]    349014E2-54AB-41C5-8072-9278D1829F5A

[dbo].[SysProfileData].[ModifiedOn]    B1B78E04-2D3D-414D-BD1F-565D9D96213E

[dbo].[SysProfileData].[ModifiedOn]    553596E4-06D1-4299-B012-F2098849E271

[dbo].[SysProfileData].[ModifiedOn]    D453578C-DB8C-4ECC-918A-26ED068054F4

[dbo].[SysProfileData].[ModifiedOn]    2F316056-B411-4FEF-BBD2-47CC5167320E

[dbo].[SysProfileData].[ModifiedOn]    DD200005-1F2F-4891-B3F2-32EF08CEF537

[dbo].[SysProfileData].[ModifiedOn]    E80BE419-186B-4AFA-A726-8CFC362DCAB1

[dbo].[SysProfileData].[ModifiedOn]    EFE8B4C8-6612-42EB-A39C-2418ACFB532D

 

Если смотреть конкретно по записям SysProfileData, то там дата текущего часового профиля, а не UTC. Т.е. если в моем запросе заменить GETUTCDATE() на GETDATE(), то скрипт больше не выдает эти записи. На либо баг сохранения данных в БД.

Но не дают покоя эти записи 

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

тут больше похоже на баг в поставке.

Террасофт, что скажите?

И у кого есть такие записи из будущего?

 

Версия 7.17.1

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

Добрый день, Алексей.

Уведомим о данной проблеме ответственную команду разработки, чтобы внесли изменения в последующих релизах.

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

Всем привет. Столкнулся с такой проблемой:

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

Очень долго выполнялась бизнес-логика, когда пользователь CRM в странице редактирования Обращения пытается подгрузить шаблон письма. 

Запустил в SQL Profiler трасировку, выполнил действие, нашел.

Заметил, что Duration гораздо больше CPU + Reads, и нет никакого плана выполнения для такого запроса.

Сталкивался ли кто с подобной ситуацией? Какие меры предпринимали?

Я так понимаю, что рано или поздно данная ситуация возникает у всех, если развивать СРМ с куча интеграций и т.п., получения обращений в систему с 5 почт, подключением сотрудников в количестве от 30-48.

Ресурсов у сервера БД достаточно, 2 виртуалки, по 2 ТБ памяти, по 98 ГБ ОЗУ, процессор 2.4Ггц X 12 ядер.

Нравится

9 комментариев

Саид, как видно со скриншота, это запрос на вставку в таблицу активностей записи с названием "Диагностировать и решить инцидент #...".

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

Или дело в какой-то глобальной блокировке на таблицу, наложенную одновременнно работающей другой логикой.

Не пробовали аналогичный запрос (естественно, с другим Id) запускать из Management Studio вручную, так тоже тормозит?

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

Да, это на добавление активности "Диагностировать  и решить инцидент ..." запись в трасировке, я забыл в описании указать. В следующий раз попробую через Management Studio выполнить запрос. Вот не знаю почему, но после добавления 2 индексов в SysCaseRight действия такие, как Отправка письма в обращении и т.д., переход между состояниями в кейсе страницы редактирования, стали работать быстрее заметно.

Саид, после добавления индексов ускорилась же не работа конкретного запроса вставки активности, а всё действие? Может, там перед этим (или после) ещё был длительный запрос чтения обращений с учётом прав, он и ускорился?

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

Да, он ускорился.

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

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

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

Здравствуйте!

Нужно сделать некий отчет, который будет содержать информацию по активностям, в том числе вычисляемые поля по количеству активностей, их длительности и тп. На вход отчету нужно задавать как минимум диапазон дат. Стандартными итогами такой отчет получить не могу, т.к. конструктор не позволяет выполнять вычисления. Планирую сделать sql view, но в нее не знаю как передавать параметры, взятые из фильтра. Помогите, пожалуйста, с передачей параметров.

Нравится

6 комментариев

Отчет где будет строиться?

1) Был опыт вывода view в итоги

2) В excel отчеты

3) подключение вычисляемых полей из view к реестру раздела

Добрый день! Вы строите View c набором итоговых столбцов по которым уже и будите фильтровать из интерфейса.

Вот пример моего представления:

CREATE VIEW dbo.[VwDynamicOsago] ([Id],[CreatedAt],[WeekId],[MonthId],[Name], [InsuranceCount], 
[AvgPolicyCost], [PolicyIncome], [Cpa], [ProfitByOnePolicy], [Turnover], [Revenue], [AdsCost], [Profit], 
[MultiplexCoeff], [SingleTax], [BankExpenses], [MotivationCC],[BankRatio]) AS
SELECT 
	NEWID() [Id],	
	CONVERT(date, DATEADD(HOUR, dbo.fn_AbGetAddedHoursToSqlQuery(), [I].[CreatedAt])) [CreatedAt],
	[I].[WeekId] [WeekId],
	[I].[MonthId] [MonthId],
	'Динамика '+'('+CONVERT(varchar(10), DATEADD(HOUR, dbo.fn_AbGetAddedHoursToSqlQuery(), [I].[CreatedAt]), 120)+')' [Name],
	COUNT([I].[Id]) [InsuranceCount],
	AVG([I].BrokerDiscountedPayment) [AvgPolicyCost],
	AVG([I].Revenue) [PolicyIncome],
	dbo.fn_AbCalculateCpa([CpcCost].[AdsCost], COUNT([I].[Id])) [Cpa],
	dbo.fn_AbCalculateProfitByOnePolicy(SUM([I].Revenue), 
										dbo.fn_AbCalculateSingleTax(SUM([I].[Commission]), 5), 
										dbo.fn_AbCalculateBankExpenses(AVG([I].Revenue), dbo.fn_AbGetBankRatio(CONVERT(date, DATEADD(HOUR, dbo.fn_AbGetAddedHoursToSqlQuery(), [I].[CreatedAt])))), 
										dbo.fn_AbCalculateMotivationCC(SUM(CC_MOTIVATION.[Value]), COUNT([I].[Id])), 
										[CpcCost].[AdsCost], 
										COUNT([I].[Id])
										) [ProfitByOnePolicy],	
	SUM([I].BrokerDiscountedPayment) [Turnover],
	SUM([I].Revenue) [Revenue],
	[CpcCost].[AdsCost] [AdsCost],
	dbo.fn_AbCalculateProfit(SUM([I].Revenue), 
							 dbo.fn_AbCalculateSingleTax(SUM([I].[Commission]), 5), 
							 dbo.fn_AbCalculateBankExpenses(AVG([I].BrokerDiscountedPayment), dbo.fn_AbGetBankRatio(CONVERT(date, DATEADD(HOUR, dbo.fn_AbGetAddedHoursToSqlQuery(), [I].[CreatedAt])))), 
							 dbo.fn_AbCalculateMotivationCC(SUM(CC_MOTIVATION.[Value]),	COUNT([I].[Id])), 
							 [CpcCost].[AdsCost]
							 ) [Profit],
	IIF([CpcCost].[AdsCost] IS NOT NULL AND [CpcCost].[AdsCost] &gt; 0, SUM([I].Revenue)/[CpcCost].[AdsCost],0) [MultiplexCoeff],
 
	dbo.fn_AbCalculateSingleTax(SUM([I].[Commission]), 5) [SingleTax],
	dbo.fn_AbCalculateBankExpenses(AVG([I].BrokerDiscountedPayment), dbo.fn_AbGetBankRatio(CONVERT(date, DATEADD(HOUR, dbo.fn_AbGetAddedHoursToSqlQuery(), [I].[CreatedAt])))) [BankExpenses],
	dbo.fn_AbCalculateMotivationCC(SUM(CC_MOTIVATION.[Value]), COUNT([I].[Id])) [MotivationCC],
	dbo.fn_AbGetBankRatio(CONVERT(date, DATEADD(HOUR, dbo.fn_AbGetAddedHoursToSqlQuery(), [I].[CreatedAt]))) [BankRatio]
 
FROM [AbInsurance] [I] WITH(NOLOCK)
LEFT OUTER JOIN [CpcCost] [CpcCost] WITH(NOLOCK) ON [CpcCost].[Date] = CONVERT(date, DATEADD(HOUR, dbo.fn_AbGetAddedHoursToSqlQuery(), [I].[CreatedAt]))
OUTER APPLY (SELECT SUM(IIF( DATEPART(HOUR, DATEADD(HOUR,dbo.fn_AbGetAddedHoursToSqlQuery(),CreatedAt)) &gt; 18, 50, 40)) [Value]
			 FROM [AbInsurance] [I1] WITH(NOLOCK)
			 WHERE [I1].ProcessingReasonCCId IS NOT NULL AND [I1].Id = [I].Id
			 GROUP BY CONVERT(date,DATEADD(HOUR, dbo.fn_AbGetAddedHoursToSqlQuery(), [I1].[CreatedAt]))
			 ) AS CC_MOTIVATION
WHERE [I].StatusId = '195CD1AD-37B3-4F0A-B4FC-70E2BF0B3F06'
		AND [I].[CreatedAt] IS NOT NULL
GROUP BY CONVERT(date, DATEADD(HOUR, dbo.fn_AbGetAddedHoursToSqlQuery(), [I].[CreatedAt])), 'Динамика  '+'('+CONVERT(varchar(10), DATEADD(HOUR, dbo.fn_AbGetAddedHoursToSqlQuery(), [I].[CreatedAt]), 120)+')', [CpcCost].[AdsCost], [I].[MonthId], [I].WeekId

 

Может, лучше не создавать динамически view под каждый запуск отчёта, а при его запуске формировать программно в ESQ или Select выборку с нужными условиями и группировками и записывать её  результаты в некоторую (одну и ту же) служебную таблицу, добавив в отдельную колонку Id запуска. А при построении отчёта фильтровать её по этому Id. А когда после построения отчёта эти записи станут ненужными, чистить.

Александр, Ваша идея очень интересна. Спасибо! Объясните, пожалуйста, вкратце как можно на вкладке с итогами добавить контролы дат, для запроса диапазона дат у пользователя и кнопки Сформировать для инициирования формирования ESQ.

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

 

Вам необходимо реализовать страницу настроек отчёта (пример схемы в конфигурации — ContactAnniversariesReportFilter) и зарегистрировать её в БД, в таблице SysModuleAnalyticsReport, в колонке SysOptionsPageSchemaUId записи Вашего отчёта.

 

Для конкретной реализации с вычислениями, видимо, нужно будет сделать логику записи результатов в таблицу, а затем передавать в отчёт один параметр — Id для фильтрации.

Нигрескул Алексей пишет:

Добрый день! Вы строите View c набором итоговых столбцов по которым уже и будите фильтровать из интерфейса.

Алексей, ведь в стандартных итогах нет штатного фильтра. Можно будет только выгрузить всю таблицу в эксель и там уже средствами экселя фильтровать. А это очень неудобно. Или можно как-то добавить стандартный фильтр к произвольной вьюхе?

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

Добрый день, коллеги.

У нас недавно была внедрена система terrasoft bpmonline которая использует MS SQL. Хотелось бы узнать, есть ли какие-то рекомендованные регламентные процедуры по поддержке этой СУБД. У меня есть относительно большой опыт в поддержке MS SQL для 1С и там к стандартным регламентным процедурам относят перестроение индексов, сбор статистики и очистка процедурного кеша. Эти операции реально помогают производительности 1С. Скажите, имеет ли смысл применять подобные регламентные операции для MS SQL в случае terrasoft bpmonline? Возможно, terrasoft имеет какие-то свои рекомендации (к сожалению, пока не сталкивался с ними) ? Заранее спасибо за ответ.

Нравится

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

Игорь, в общем случае всё будет очень похоже. Всё те же индексы и прочее.

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

Например, в SysUserSession при каждом входе пользователя или какой-то интеграции пишется новая запись. Если её никогда не чистить, она вырастает до больших размеров и работа с ней замедляется, встречаются deadlock-и. Аналогично, в IntegrationLog пишется информация при работе интеграций, если такие предусмотрены в Вашей системе. Другие подобные таблицы можно увидеть, построив в Management Studio отчёт «Disk Usage by Top Tables».

Плюс в оптимизации стоит учитывать, что в Terrasoft повсеместно используются в качестве первичных ключей GUID-ы.

Иногда объёмы данных столь велики, что для нормального выполнения запросов помогает только переход на SSD, поскольку HDD не справляется. И версию MS SQL лучше выбрать 2016 и новее.

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

 Большое спасибо за Ваш ответ.

Показать все комментарии
Идея
Одобрена

 

Для поиска запросов, которые выполняются долго,  используем профайлер. В нём невозможно увидеть имя пользователя или машину инициатора запроса, т.к. они одинаковые для всех, и соответственно равны пользователю из строки подключения к БД и машине, на которой выполняется приложение.

Идея заключается в следующем: можно добавлять в запрос Id SysAdminUnit'а (и любую другую полезную информацию) как комментарий.Это упростит поиск некоторых проблем, а реализация этой функции не требует серьезных доработок и никак не повлияет на выполнение самих запросов.

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

Здравствуйте!

Передали данное пожелание команде разработки для анализа возможности внедрения данного функционала в будущих версиях системы.

Спасибо большое)

Добрый день!

Спасибо, идея принимается. Планируем сделать в ближайших релизах.

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

Здравствуйте! Я в террасофте совсем новичок, только начинаю изучать. Версия ТС - 3.4.0.38. По форуму искала, вроде подходящего решения не нашла, либо не поняла что это "оно". Подскажите пожалуйста!
Была поставлена задача - по расписанию формировать файл с отчетом для Excel (есть аналог для работы пользователя в FR), выкладывать его в сеть и отправлять группе лиц.
Вроде как все решила через SQL, правда экселевский файл сформировала через spread xls на xml.
Несущественная проблема - при открытии на некоторых компьютерах ругается на несоответствие формата, с этим можно жить, но вот на телефонах этот файл не открывается в приложениях, но очень нужно.
В итоге встал вопрос о другом формате.. Возможно ли как то через sql или сам террасофт выполнить по расписанию формирование файла в формате xlsx или pdf (редактируемый)? Либо конвертацию сделать, может что-то вроде - открыть файл в sql через sp_OACreate 'Excel.Application', и сохранить его в xlsx..

Нравится

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

С помощью Terrasoft, также можно выполнить такую задачу, для этого необходимо на сервер создать задачу (Task Scheduler), которая будет запускаться по времени и вызывать Terrasoft командой TSClient.exe /wnd=wnd_ExportRep.

Где в окне wnd_ExportRep будет прописана логика экспорта.
Обратите внимание на сервисы scr_MSExcelLibrary, scr_MSExcelLibraryConsts, а также на сервис scr_UserReportCommon, в особенности на функцию GetExcelObject - которая возвращает Com объект на Excel.

Также можно изучить работу сервиса scr_ImportExcelWizardUtils, который автоматически создает отчеты в Excel, на основании его работы можете создать свой экспорт.

Хороший вариант! Спасибо! Правда мне очень много стоит изучить для реализации подобного..
А клиент терры будет открыватся на сервере или только процесс висеть? Если есть возможность подсказать подобные примеры решения буду очень признательна.

Пробовала запускать excel на террасофте через var ExcelApp = new ActiveXObject("Excel.Application");
но система выругалась на меня и клиент вылетел..

Можете взять мой пример запуска коннектора и создание Excel файла.
Алгоритм следующий:
1. Создайте файле с расширением js
2. Пропишите в нем следующий код:

function WSLog(LogText) {
	WScript.stdout.WriteLine(LogText);
}
 
function GetExcelObject() {
	var Excel = new ActiveXObject('Excel.Application');
	var Excel_wb = Excel.Workbooks.Add();
	Excel.Sheets(1).Name = "Данные";
	var SheetsCount = Excel.Sheets.Count;
	for (var i = 2; i <= SheetsCount; i++) {
		Excel.Sheets(2).Delete();
	}
	Excel.Visible = false;
	return Excel;
}
 
function Main() {
	var args = WScript.arguments;
	var ConfigurationName = "TS_3.4.1.113_XRM_SD_SoftKey_ENU_Tereshchuk";
	var AuthenticationMode = 1; //1 - DatabaseServer, 0 - Windows
	var UserName = "Supervisor";
	var UserPassword = "";
	var ExcelFileName = 'C:\\Temp\\TestExcel.xlsx';
	WSLog("Start!");
	var Connector =  new ActiveXObject('TSObjectLibrary.Connector');
	var Config;
	if (AuthenticationMode) {
		Config = Connector.OpenConfigurationByName(ConfigurationName, AuthenticationMode, UserName, UserPassword);
	} else {
		Config = Connector.OpenConfigurationByName(ConfigurationName, AuthenticationMode);
	}
	var Excel = GetExcelObject();
	Excel.Sheets(1).SaveAs(ExcelFileName);
	Excel.Visible = true;
	Connector.Logoff();
	WSLog("Finish!");
}
 
Main();

3. Создайте файл с расширением bat и пропишите в нем код:
%WinDir%/SysWOW64/cscript.exe /d D:\Projects\JS\RunTS.js

4. Запустите bat файл

Исходники: js.zip

Спасибо!
Так как задача была горящей, а 'Excel.Application' наотрез отказывается работать, временно решила через excelcnv.exe. Там правда очень много нюансов, за счет чего код получился совсем извращенным, но главное рабочим.. позже вернусь к приведению в нормальный вид ) попробую все-таки решить через террасофт по #1 предложенному ответу.

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

Установка цвета для записи раздела происходит в функции grdDataOnGetRowDrawInfo сервиса scr_UsersGridArea.

Пользователь отображается серым цветом, только в том случае, если значение поле [IsInDatabase] источника данных ds_UserScript содержит enmNo.

Установка значения вычисляемого поля [IsInDatabase] происходит в событии OnDatasetCalcFields источника данных ds_UserScript:

     var SQLObjectName = GetDatasetFieldValue(Dataset, 'SQLObjectName');
     if (IsEmptyValue(SQLObjectName)) {
        return;
    }
    var IsInDatabase = Connector.DBEngine.GetIsUserExists(SQLObjectName);
    if (IsInDatabase) {
        Dataset.Values('IsInDatabase') = enmYes;
    } else {
        Dataset.Values('IsInDatabase') = enmNo;
    }

Функция ядра Connector.DBEngine.GetIsUserExists(SQLObjectName) возвращает true, только при условии, что sql запрос вернет значение равное 1:

SQL:

SELECT count(*) FROM [sysusers] WHERE [name] = 'LoginName' AND [issqlrole] = 0

Oracle:

SELECT COUNT(*) AS CNT FROM ALL_USERS  WHERE UPPER(USERNAME) = (SELECT UPPER("tbl_AdminUnit"."SQLObjectName")as NM FROM "tbl_AdminUnit" WHERE "tbl_AdminUnit"."SQLObjectName"  = 'LoginName');

где LoginName - логин пользователя на сервере

Примечание
Если sql запрос в orcale вернул значение больше 1, необходимо проверить параметры сессии (скорей всего не учитывается регистр в условии):
NLS_COMP
NLS_SORT

Регистр не учитывается:
NLS_COMP=ANSI;
NLS_SORT=BINARY_CI;

Регистр учитывается:
NLS_COMP=BINARY;
NLS_SORT=RUSSIAN;

Установить параметры сессии можно таким запросом:

ALTER SESSION SET NLS_COMP=BINARY;
ALTER SESSION SET NLS_SORT=RUSSIAN;

Нравится

Поделиться

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

в продолжение темы http://www.community.terrasoft.ru/blogs/10000
версия 2 :smile:

Чтобы в MSSQL из строки получить набор строк (например, для использования в качестве параметра для select ... where ... in (***)), предлагаю следующее:

declare @input_str nvarchar(4000) = '' -- входная строка
declare @IncludedTablesStringTable TABLE (Code uniqueidentifier) -- смени тип
declare @IncludedTablesStringCode nvarchar(4000)
declare @delimeter nvarchar(4000) = ', '
declare @pos int = 0
declare @len int = LEN(@input_str + cast(2 AS varchar)) - 1
declare @lend int = LEN(@delimeter + cast(2 AS varchar)) - 1
declare @oldpos int = 0
declare @substr nvarchar(4000)

while (@pos = @len)
begin
        SET @substr = SUBSTRING(@input_str, @pos, @lend)
        IF (@substr = @delimeter OR @pos = @len)
        begin
                SET @substr = SUBSTRING(@input_str, @oldpos,
                        @pos - @oldpos + case when (@pos = @len) then 1 else 0 end
                )
                INSERT INTO @IncludedTablesStringTable (Code) VALUES (@substr)
                SET @pos = @pos + @lend
                SET @oldpos = @pos
                continue
        end
        SET @pos = @pos + 1
end

(SELECT Code FROM @IncludedTablesStringTable)

Комментарии:
- для использования вставляете (select Code from @IncludedTablesStringTable) туда, где нужен набор строк

- почему все строки nvarchar(4000)? Меня учили, что программа должна работать как можно в большей вариантивности входящих значений. А так как ничто не мешает использовать какую-то странную кодировку или какой-то гигантский разделитель, из ограничений на переменные поставил только юникод.

- что это?

declare @len int = LEN(@input_str + cast(2 AS varchar)) - 1
declare @lend int = LEN(@delimeter + cast(2 AS varchar)) - 1
дело в том, что нам нужен размер разделителя и строки, но LEN() обрезает пробелы в конце (из-за этого я потратил на часок больше времени :cry:). Поэтому идем на хитрость: добавляем знак в конце, считаем, отнимаем единицу. Ну а CAST() используется т.к. если вставлять код со строками в exec(), то начинаются сложности всякие, а так - мы обходим эту проблему. Конечно, можно использовать и другие решения для учета конечных пробелов, но все, что придумал, показались не надежными

- скрипт начинает путаться если разделители идут подряд (не разделены смыслом :lol:), т.е. при разделителе ',' строка '12345,6789,321,,,' распарсится в

12345
6789
321

,

- и последнее, в declare @IncludedTablesStringTable не забудьте указать тип данных тот, который вам нужен

Нравится

Поделиться

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

вот тут разбираются нормальные способы :lol:
https://sqlperformance.com/2012/07/t-sql-queries/split-strings

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