powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Результат хранимки через ADO
47 сообщений из 47, показаны все 2 страниц
Результат хранимки через ADO
    #39109713
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Функция:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
USE [tam]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER FUNCTION [dbo].[fn_FldType] (@tabName nvarchar(50), @fldName nvarchar(50))
RETURNS nvarchar(50)
AS
BEGIN
	DECLARE @fldType nvarchar(50)

	SELECT @fldType = 
		CONVERT(nvarchar,(SELECT TYPE_NAME(c.user_type_id) AS TypeName	
		FROM sys.objects AS o JOIN sys.columns AS c  ON o.object_id = c.object_id
		WHERE o.name=@tabName and c.name=@fldName))	

	RETURN @fldType
END


хранимка, где она юзается:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
USE [tam]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--Данные в строку
ALTER PROCEDURE [dbo].[hp_SQLstr] 
	@SQL nvarchar(3000), @tabName nvarchar(50), @fldName nvarchar(50), @spr nvarchar(5), @ResultVar nvarchar(3000) OUTPUT
AS
DECLARE @fldType nvarchar(50), @fldName_tmp nvarchar(50), @SQL_tmp nvarchar(3000)
 
BEGIN
	SET NOCOUNT ON;

	SELECT @fldType = (SELECT dbo.fn_FldType(@tabName, @fldName))
	IF @fldType = 'int' OR @fldType = 'decimal'
		SET @fldName_tmp = 'CONVERT(nvarchar,' + @fldName + ')'
	IF @fldType = 'smalldatetime' OR @fldType = 'datetime'
		SET @fldName_tmp = 'CONVERT(nvarchar,' + @fldName + ', 104)'
	
	If CHARINDEX('ORDER BY', @SQL) > 0 And CHARINDEX('TOP', @SQL) = 0 
		SET @SQL = REPLACE(@SQL, 'SELECT ', 'SELECT TOP 100 PERCENT ')

	SET @SQL_tmp =
		'SELECT @ResultVar = (SELECT (SELECT DISTINCT ' + @fldName_tmp + '+''' + @spr + '''' + 
		' FROM (' + REPLACE(@SQL, '''', '''''') + ') AS tmp FOR XML PATH('''')) collate Cyrillic_General_100_CI_AS)'
	EXEC sp_executesql @SQL_tmp, N'@ResultVar nvarchar(3000) OUTPUT', @ResultVar = @ResultVar OUTPUT
	IF @ResultVar <> '' 
		SET @ResultVar = SUBSTRING(@ResultVar, 1, Len(@ResultVar) - 1)
END


Запускаю в менеджере SQL
Код: sql
1.
2.
3.
4.
USE tam;
DECLARE @ResultVar nvarchar(1000);
EXECUTE hp_SQLstr 'SELECT Zak_ID FROM tab_Zakaz', 'tab_Zakaz', 'Zak_ID', ',', @ResultVar OUTPUT;
SELECT @ResultVar;


выдает 1,2,3... и т. д. - работает стало быть

Запускаю через ADO (VBA):
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
Dim sSQL As String, ResultVar As String

sSQL = _
    "USE tam;" & _
    "DECLARE @ResultVar nvarchar(1000);" & _
    "EXECUTE hp_SQLstr 'SELECT Zak_ID FROM tab_Zakaz', 'tab_Zakaz', 'Zak_ID', ',', @ResultVar OUTPUT;" & _
    "SELECT @ResultVar AS RecVar;"
ResultVar = Nz(con.Execute(sSQL).NextRecordset.Fields(0), "")


выдает "переменная объекта или переменная не задана"
другие процедуры, запускаемые аналогично отрабатываются, эта не хочет. В чем прикол?

Модератор: Тема перенесена из форума "Microsoft SQL Server".
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39109728
Palarm,

дык в форуме VB и надо спрашивать
пока вероятность того что какой-нибудь con не инициализирован примерно равна вероятности того что что-то не так с OUTPUT у адо
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39109734
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а так?
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
Dim sSQL As String, ResultVar As String

sSQL = _
    "USE tam;" & _
    "SET NOCOUNT ON " & _
    "DECLARE @ResultVar nvarchar(1000);" & _
    "EXECUTE hp_SQLstr 'SELECT Zak_ID FROM tab_Zakaz', 'tab_Zakaz', 'Zak_ID', ',', @ResultVar OUTPUT;" & _
    "SELECT @ResultVar AS RecVar;"
ResultVar = Nz(con.Execute(sSQL).Fields(0), "")

и еще SET NOCOUNT ON первой строкой в хранимку.

А вообще, в ADO есть ADODB.Command для выполнения процедур
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39109825
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Родил таки:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Dim ResultVar As String
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command

Set cmd.ActiveConnection = con
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "hp_SQLstr"

cmd.Parameters.Append cmd.CreateParameter("@SQL", adVarWChar, adParamInput, 3000, "select zak_id from tab_zakaz")
cmd.Parameters.Append cmd.CreateParameter("@tabName", adVarWChar, adParamInput, 50, "tab_Zakaz")
cmd.Parameters.Append cmd.CreateParameter("@fldName", adVarWChar, adParamInput, 50, "Zak_ID")
cmd.Parameters.Append cmd.CreateParameter("@spr", adVarWChar, adParamInput, 5, ",")
cmd.Parameters.Append cmd.CreateParameter("@ResultVar", adVarWChar, adParamOutput, 3000)
cmd.Execute , , adExecuteNoRecords
ResultVar = cmd.Parameters("@ResultVar").Value



Но блин, только с этой хранимкой такая трабла, остальные отрабатываются как выше написал.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39109832
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Потому что другие хранимки не генерят дополнительные сообщения (которые подавляет set nocount on)

ЗЫ: Если лень писать кучу CreateParameter, есть Parametes.Refresh, который получает готовую коллекцию параметров с сервера (лишний, но часто не очень принципиальный запрос к серверу)
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39109836
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command

cmd.ActiveConnection = con
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "hp_SQLstr"
cmd.Parameters.Refresh
cmd.Execute , Array("select zak_id from tab_zakaz", "tab_Zakaz", "Zak_ID", ",", ""), adExecuteNoRecords
fun = cmd.Parameters("@ResultVar").Value


Получаем Null.
Хотелось бы функцию на VB сделать, типа:

funSQLstr("параметры через разделитель")

почему и потребность запустить хранимку с минимумом букв. Но если через CreateParameter делать, придется кроме вышеназванных еще и adVarWChar (или другой какой тип) и длину указывать. Потому как при adBSTR выдает опять же Null, а adVarWChar требует обязательной длины строки.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39109838
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProПотому что другие хранимки не генерят дополнительные сообщения (которые подавляет set nocount on)А почему тогда к примеру эта работает по старому вызову?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
USE [tam]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--Вставка цен ТМЦ по разрешительным документам
ALTER PROCEDURE [dbo].[hp_InsertWrDoc] 
	@MatCenaID INT, @KartID INT, @RecCnt INT OUTPUT
AS
DECLARE @FROM nvarchar(1000), @SQL nvarchar(3000)
 
BEGIN
	SET NOCOUNT ON;

	--вставка в карточку ТМЦ
	IF @MatCenaID = 0
		BEGIN
			SET @FROM = 
				'FROM	tab_WRDoc INNER JOIN 
						tab_UKT_ZED_WRDoc ON tab_WRDoc.WRD_ID = tab_UKT_ZED_WRDoc.WRD_ID INNER JOIN 
						tab_MKart ON tab_UKT_ZED_WRDoc.UKT_ID = tab_MKart.UKT_ID 
				 WHERE  tab_MKart.Kart_ID=' + CONVERT(nvarchar,@KartID) + ' AND tab_WRDoc.WRD_ID NOT IN
						(SELECT WRD_ID 
						FROM	tab_MCena_WRDoc 
						WHERE	Kart_ID=' +  CONVERT(nvarchar,@KartID) + ')'
			SET @SQL = 'SELECT @RecCnt = COUNT(*) ' + @FROM 
			EXEC sp_executesql @SQL, N'@RecCnt INT OUTPUT', @RecCnt = @RecCnt OUTPUT
			IF  @RecCnt > 0
				BEGIN
					SET @SQL = 
						'INSERT INTO tab_MCena_WRDoc (Kart_ID, WRD_ID)
						SELECT ' + CONVERT(nvarchar,@KartID) + ',tab_WRDoc.WRD_ID ' + @FROM
					EXEC sp_executesql @SQL
				END
		END
	ELSE --вставка в цены ТМЦ
		BEGIN
	        SET @FROM = 
            'FROM   tab_MCena_WRDoc 
			WHERE	Kart_ID=' +  CONVERT(nvarchar,@KartID) + ' AND ISNULL(NumDoc,N'''')='''' AND WRD_ID NOT IN
					(SELECT WRD_ID 
					FROM	tab_MCena_WRDoc 
					WHERE	MatCena_ID=' + CONVERT(nvarchar,@MatCenaID) + ')'
			SET @SQL = 'SELECT @RecCnt = COUNT(*) ' + @FROM
			EXEC sp_executesql @SQL, N'@RecCnt INT OUTPUT', @RecCnt = @RecCnt OUTPUT
			IF  @RecCnt > 0
				BEGIN
					SET @SQL = 
						'INSERT INTO tab_MCena_WRDoc(MatCena_ID, WRD_ID)
						SELECT ' + CONVERT(nvarchar,@MatCenaID) + ',tab_MCena_WRDoc.WRD_ID ' + @FROM
					EXEC sp_executesql @SQL
				END
		END
END


"дополнительные сообщения" - что имеете в виду?
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39109860
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PalarmА почему тогда к примеру эта работает по старому вызову?потому что в ней есть set nocount on

Palarm"дополнительные сообщения" - что имеете в виду?типа тех, которые выдает студия после выполнения запроса: "(1 row(s) affected)", а также варнинги, принты и т.п. Чтобы их все перебрать на клиенте используется NextRecordset в нужном количестве. А поскольку морочиться нужным количеством дело неблагодарное, обычно их подавляют set nocount on
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39109866
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Palarm
Код: vbnet
1.
cmd.Execute , Array("sel


msdnParameters
Optional. A Variant array of parameter values used in conjunction with the input string or stream specified in CommandText or CommandStream. (Output parameters will not return correct values when passed in this argument.)

я никогда так не вызывал, просто писал:
Код: vbnet
1.
2.
cmd.Parameters("@MyParameter1") = Value1
cmd.Parameters("@MyParameter2") = "Value2"

не знаю, как себя поведет указание Parameters в Execute, но по хелпу мне кажется, что это не то

разумеется, была функция-обертка для вызова процедур
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39110016
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
потому что в ней есть set nocount on
его не было только в функции - добавил туда, так же требует чего то задать. Ставить подавление первой строкой тоже не помогло. Чую, тут какая то фигня простая, а мессага может вообще не о том верещит. Ну да пес с ней, сделал обертку конкретно под эту хранимку.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
Function funSQLStr(ByVal sSQL As String, ByVal sTabFieldName As String, Optional ByVal sSeparator As String) As String
Dim cmd As ADODB.Command

On Error GoTo Err_
    If sSeparator = "" Then sSeparator = ","

    Set cmd = New ADODB.Command
    cmd.ActiveConnection = CollCon(ConName)
    cmd.CommandType = adCmdStoredProc
    cmd.CommandText = "hp_SQLstr"
    
    cmd.Parameters.Append cmd.CreateParameter("@SQL", adVarWChar, adParamInput, 3000, sSQL)
    cmd.Parameters.Append cmd.CreateParameter("@tabName", adVarWChar, adParamInput, 50, Split(sTabFieldName, ".")(0))
    cmd.Parameters.Append cmd.CreateParameter("@fldName", adVarWChar, adParamInput, 50, Split(sTabFieldName, ".")(1))
    cmd.Parameters.Append cmd.CreateParameter("@spr", adVarWChar, adParamInput, 5, sSeparator)
    cmd.Parameters.Append cmd.CreateParameter("@ResultVar", adVarWChar, adParamOutput, 3000)
    cmd.Execute , , adExecuteNoRecords
    funSQLStr = cmd.Parameters("@ResultVar").Value
Exit Function

Err_:
    Call ErrorBases(Err, "mdl_Tools", "funSQLStr")
End Function
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39110020
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть подозрение, что хранимка не пашет через execute потому, что там есть вызов функции, чего нет в других хранимках, которые запускаются нормально. По крайней мере вызов самой функции дает такую же месагу, если делать так:
Код: vbnet
1.
ResultVar = Nz(con.Execute("SELECT dbo.fn_FldType('tab_Zakaz','Zak_ID')"), "")


А в менеджере отрабатывает нормально. И запуск хранимки в другой хранимке так же отрабатывает нормально:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
USE [tam]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--Вставка разрешительных документов
ALTER PROCEDURE [dbo].[hp_InsertMCenaWrDocZak] 
	@ZakID INT, @sInsertRecords varchar(3000), @RecCount INT OUTPUT
AS
DECLARE @MatCenaID INT

BEGIN
	SET NOCOUNT ON;

	IF (SELECT Kart_ID FROM tab_MCena WHERE Zak_ID = @ZakID) = 0
		BEGIN
			DECLARE Cur1 CURSOR LOCAL FAST_FORWARD FOR
			SELECT MatCena_ID FROM tab_MCena Where MatCena_ID IN(REPLACE(@sInsertRecords, '|', ','))
		END
	ELSE
		BEGIN
			DECLARE Cur1 CURSOR LOCAL FAST_FORWARD FOR
			SELECT MatCena_ID FROM tab_MCena WHERE MatCena_ID IN(REPLACE(@sInsertRecords, '|', ',')) AND Kart_ID NOT IN(SELECT Kart_ID FROM tab_MCena WHERE Zak_ID = @ZakID)  
		END

	SET @RecCount = 0
	OPEN Cur1
	FETCH NEXT FROM cur1 INTO @MatCenaID
	WHILE @@FETCH_STATUS = 0
	BEGIN
		EXEC dbo.hp_InsertMCenaWrDocZak_sub @ZakID, @MatCenaID
		FETCH NEXT FROM Cur1 INTO @MatCenaID
		SET @RecCount = @RecCount + 1
	END

	CLOSE Cur1
	DEALLOCATE Cur1
END


Стало быть все зло от функций - осталось лишь найти какое. Было бы проще (меньше буковок писать) во многих случаях вместо хранимок с выходными параметрами вызывать функции через Execute - но они вообще так не взлетают. Видимо надо делать их запуск так же через cmd.Parameters с оберткой на VB?
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39110057
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Palarmвызов самой функции дает такую же месагу, если делать так:
Код: vbnet
1.
ResultVar = Nz(con.Execute("SELECT dbo.fn_FldType('tab_Zakaz','Zak_ID')"), "")

потому что тут-то возвращается рекордсет и надо обращаться с ним как с рекордсетом:

Код: vbnet
1.
ResultVar = con.Execute("SELECT dbo.fn_FldType('tab_Zakaz','Zak_ID')").Fields(0).Value




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

Еще момент - пользователь, под которым ты выполняешь это в студии и в АДО. Дело в том, что при обычной процедуре достаточно прав только на процедуру, в случае же динамических запросов нужны права на все объекты, которые выполняются в динамике и все таблицы которые запрашиваются в динамике.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39110063
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Proпотому что тут-то возвращается рекордсет и надо обращаться с ним как с рекордсетом
Точно! :)

Shocker.ProЕще момент - пользователь, под которым ты выполняешь это в студии и в АДО. Дело в том, что при обычной процедуре достаточно прав только на процедуру, в случае же динамических запросов нужны права на все объекты, которые выполняются в динамике и все таблицы которые запрашиваются в динамике.Это да, но у меня пока смешанная авторизация: коннект к серваку через sa либо юзера с правами на все объекты кроме их модификации - а дальше на клиенте раздача на объекты приложения. Когда доберусь до админских дел - это будет отдельная грабля.
Спасибо за помощь :)
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39110370
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лапочка однако оказалась не та, пришлось ее разбить. Собрать данные в строку из запроса типа
Код: sql
1.
select zak_id from tab_zakaz


не вопрос, а вот начиная с
Код: sql
1.
select convert(varchar, zak_id) as Rec from tab_zakaz


пошли пляски с бубном
Код: sql
1.
select convert(varchar, zak_id) + ' - ' convert(varchar, zak_id) AS ...


тут вообще карнавал. Потому как пишут в тырнетах и сам убедился динамический запрос типа
Код: sql
1.
' ... FROM (' + @SQL + ')...


ацкое зло. Прикольно, что funSQLStr() у меня вообще то есть на VBA и работает прекрасно со всякими запросами, потому что траблы кавычками там не выходит. Дай думаю ее на T-SQL сделаю, говорят перенос логики на сервер признак ума. Ага
Как говорится: не мешай механизму работать.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39110502
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я вообще не очень понял, зачем ты там динамику пилишь. Динамика на сервере обычно требуется редко.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39110537
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Proя вообще не очень понял, зачем ты там динамику пилишь. Динамика на сервере обычно требуется редко.В hp_SQLstr текст запроса является параметром, стало быть только динамикой и можно, в hp_InsertWrDoc пара предложений FROM одинаковые в двух местах, чтобы не писать 2 раза одно и тоже сделал динамический запрос. Привычка оптимизировать код, избегая копипаста.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39110572
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PalarmВ hp_SQLstr текст запроса является параметромэто я вижу, но, повторяю, я не понимаю зачем. По хорошему, клиент не должен думать о деталях хранения информации, и уж тем более не иметь никакого понятия о языке SQL.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39110573
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Palarmпара предложений FROM одинаковые в двух местахобычно такое оформляется в виде INLINE UDF или VIEW
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39111282
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
мне нужен только текст FROM - как создать VIEW без SELECT - не представляю.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39111312
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Palarmмне нужен только текст FROMскорее всего у тебя кривой подход, обычно не должно возникать в принципе такой необходимости. Если есть повторяемость, создаются подзапросы, которые можно вынести в VIEW или INLINE UDF.

Нет, не спорю, существуют ситуации, когда запрос приходится именно конструировать, но это исключение, а не правило. Возможно, у тебя есть в этом необходимость, но "FROM одинаковые в двух местах" - это не основание, для этого делают представления.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39111314
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Palarmмне нужен только текст FROM - как создать VIEW без SELECT - не представляю.по другому - ты мыслишь не теми категориями, видимо очень много лепил динамических запросов на клиенте в свое время. На TSQL так не пишут.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39111417
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Имеешь в виду, что надо сделать что то вроде:
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39111430
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
CREATE VIEW v_tmp
AS 
SELECT ... AS Rec
FROM ....
WHERE ...


а потом уже это подставлять в итоговый запрос как вложенное представление? Хотя странный подход - динамический вроде проще и нагляднее
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39111472
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Palarmпроще и нагляднеепочитай себя сам, что я могу добавить?
Palarmтут вообще карнавалPalarmпошли пляски с бубномPalarmсам убедился динамический запрос .... ацкое зло.если запрос, разбавленный множеством кавычек, конкатенаций, convert-ов, задвоенных кавычек, без подсветки синтаксиса и т.п. проще и нагляднее - пиши динамику.

Еще. Динамика компилируется каждый раз при вызове, каждый раз производится анализ таблиц и составляется план запроса. Не динамический запрос компилируется сразу, план составляется тоже сразу. Излишне говорить, что это влияет на производительность.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39111483
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
USE [tam]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--Источники данных форм и контролов
ALTER PROCEDURE [dbo].[hp_ObjSource] 
	@ObjName varchar(50), @RecKey INT = 0, @RecKeyList nvarchar(50) = ''
AS
DECLARE @DopWhere nvarchar(50), @SQL nvarchar(1000)
 
BEGIN
	SET NOCOUNT ON;

	--Списки
	IF @ObjName = 'UP_ID'
		SELECT UP_ID, UPKod + ' - ' + UPName AS UKod FROM tab_UsPostawki WHERE Sost=0 ORDER BY UPKod
	IF @ObjName = 'TR_ID'
		SELECT TR_ID, NameYur FROM tab_Customs_Region WHERE Sost=0 ORDER BY NameYur
	IF @ObjName = 'TTD_ID'
		SELECT TTD_ID, TTName FROM tab_Decl_Type WHERE Sost=0 ORDER BY TTName
	IF @ObjName = 'WName'
		SELECT WName FROM tab_WType WHERE Sost=0 ORDER BY WName
	IF @ObjName = 'CT_ID'
		SELECT CT_ID, Alfa2 + ' - ' + Country_Ukr FROM tab_Country WHERE Sost=0 ORDER BY Country_Ukr
	IF @ObjName = 'BR_ID'
		SELECT tab_Border.BR_ID, tab_Border.Name_In + ' - ' + tab_Border.Name_Out + ' (' + tab_Country.Country_Ukr + ')' AS RecName
        FROM   tab_Border INNER JOIN
               tab_Country ON tab_Border.CT_ID = tab_Country.CT_ID
        WHERE  tab_Border.Sost=0
        ORDER BY tab_Border.Favor DESC, RecName
	IF @ObjName = 'TR_Key'
		SELECT TR_Key, NameYur FROM tab_Customs_Region WHERE Sost=0 ORDER BY NameYur
	IF @ObjName = 'OrgKey'
		BEGIN
			IF (SELECT COUNT(*) FROM sys.objects AS O WHERE O.NAME='v_tmp') > 0
				DROP VIEW v_tmp
			ELSE
				EXEC ('CREATE VIEW v_tmp AS
					SELECT	OrgType, OrgKey, CASE WHEN ISNULL(NameSokr, '''')='''' THEN NameYur ELSE NameSokr END AS RecFld
					FROM	tab_Org
					WHERE	Sost=0')
			IF @RecKeyList = ''
				SELECT	OrgKey, RecFld
				FROM	v_tmp
				WHERE	OrgType=@RecKey
			ELSE
				BEGIN
					IF CHARINDEX('NOTIN', @RecKeyList) > 0
						BEGIN
							SET @DopWhere = SUBSTRING(@RecKeyList, 7, Len(@RecKeyList));
							SELECT	OrgKey, RecFld
							FROM	v_tmp
							WHERE	OrgType NOT IN(SELECT number FROM dbo.iter_intlist_to_table(@DopWhere))
						END					
					ELSE
						IF CHARINDEX('IN', @RecKeyList) > 0
							BEGIN
								SET @DopWhere = SUBSTRING(@RecKeyList, 3, Len(@RecKeyList));
								SELECT	OrgKey, RecFld
								FROM	v_tmp
								WHERE	OrgType IN(SELECT number FROM dbo.iter_intlist_to_table(@DopWhere))
							END									
				END
			DROP VIEW v_tmp
		END
END
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39111485
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А на клиенте соответсвенно:
Код: vbnet
1.
2.
3.
Set Me.OrgKey.Recordset = con.Execute("EXEC hp_ObjSource 'OrgKey', @RecKeyList='IN 1 3'")
Set Me.OrgKey1.Recordset = Me.OrgKey.Recordset
Set Me.OrgKey2.Recordset = con.Execute("EXEC hp_ObjSource 'OrgKey', @RecKeyList='NOTIN 1 3'")
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39111488
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так это ж опять динамика. Что тебе мешает создать статическую вьюшку, я никак не могу понять. Зачем ее каждый раз создавать и удалять?
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39111492
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Palarm
Код: sql
1.
2.
@RecKeyList nvarchar(50)
IF CHARINDEX('NOTIN', @RecKeyList) > 0

небольшое замечание по ходу дела: ты постоянно оперируешь между varchar и nvarchar-строками, то есть заставляешь сервер постоянно преобразовывать один тип данных в другой, правильно так:
Код: sql
1.
IF CHARINDEX(N'NOTIN', @RecKeyList) > 0
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39111588
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProТак это ж опять динамика. Что тебе мешает создать статическую вьюшку, я никак не могу понять. Зачем ее каждый раз создавать и удалять?Видимо долгое юзание Аксес в качестве СУБД сформировало порочные с позиции T-SQL автоматизмы мышления: динамические запросы, обработка данных на клиенте, процедурное программирование и т. д. - БД по сути использовалось как мешок для мусора, в котором надо ковыряться из клиента. В итоге со скрипом въезжаю в то, что для тебя банальности.

PS:
тут да, конечно пишем статичную вьюху - кавычки в топку
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115214
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
IF @ObjName = 'CT_ID'
    SELECT CT_ID, Alfa2 + ' - ' + Country_Ukr FROM tab_Country WHERE Sost=0 ORDER BY Country_Ukr
IF @ObjName = 'CTyp_ID'
   SELECT CTyp_ID, CTypName FROM tab_MCenaType WHERE Sost=0 ORDER BY CTypName
IF @ObjName = 'DC_ID'
   SELECT DC_ID, DocType FROM tab_Document_Type WHERE Sost=0 ORDER BY DocType
...


При таком коде не будет лишних тормозов при пробежке по If-ам, которых может быть сотни? Тут как бы просится ELSEIF которого нет в T-SQL или может здесь при нахождении нужного условия дальнейший поиск прекращается?
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115218
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProДинамика компилируется каждый раз при вызове, каждый раз производится анализ таблиц и составляется план запроса. Не динамический запрос компилируется сразу, план составляется тоже сразу. Излишне говорить, что это влияет на производительность.Я так понимаю, что запуск селекта через ADO имеет тот же негатив? То есть con.Execute(...) выполняется медленнее чем запуск хранимки через тот же con.Execute?
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115338
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PalarmПри таком коде не будет лишних тормозов при пробежке по If-ам, которых может быть сотни? Тут как бы просится ELSEIF которого нет в T-SQL или может здесь при нахождении нужного условия дальнейший поиск прекращается?Что мешает использовать else? elseif всего лишь удобная форма для записи цепочки if-ов. А вообще, правильнее под каждый селект создавать отдельную хранимку, а не пытаться запихать всю логику всего приложения в одну. Это, кстати, поможет оптимизатору SQL. Понимаю, что снова мешает менталитет программиста динамических запросов на клиенте, но, как я уже говорил, надо менять взгляды.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115343
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PalarmЯ так понимаю, что запуск селекта через ADO имеет тот же негатив? То есть con.Execute(...) выполняется медленнее чем запуск хранимки через тот же con.Execute?совершенно верно. Select - это тот же динамический запрос. Как я уже говорил выше - клиента нужно писать так, чтобы он понятия не имел про язык SQL. Он просто вызывает хранимку с определенными параметрами и получает ответ в определенном формате. Нет ничего страшного, что на сервере будет тысяча хранимок. Тебе же не мешает та же самая тысяча процедур/функций на клиенте. Так и воспринимай - хранимка, это процедура/функция, которая выполняется на сервере, а не на клиенте. И если функция на клиенте или хранимка на сервере содержит всего одну строку - в этом нет ничего страшного.

Данный подход имеет и побочный эффект: можно модернизировать хранилище, не переписывая клиента и/или сохранять совместимость со старыми версиями. Это особенно удобно, если клиентов много и взять и резко обновить всем версию клиента представляется затруднительным. Просто в новой версии обращаешься к тем же данным по-новому (новая хранимка или новые параметры хранимки, имеющие значения по умолчанию), старые клиенты продолжают работать по-старому
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115430
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProА вообще, правильнее под каждый селект создавать отдельную хранимку, а не пытаться запихать всю логику всего приложения в одну. Это, кстати, поможет оптимизатору SQL. Понимаю, что снова мешает менталитет программиста динамических запросов на клиенте, но, как я уже говорил, надо менять взгляды.
Хочешь сказать, что вот так хранимку для списка писать не кошерно, с позиwии T-SQL
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
IF @ObjName = 'OrgKey'
	BEGIN
		IF @RecKeyList = ''
			BEGIN
				IF @RecKey <> 0 AND @RecKey1 = 0
					SELECT	OrgKey, RecFld
					FROM	qry_hp_ObjSource_sub
					WHERE	OrgType=@RecKey
					ORDER BY NameYur
				IF @RecKey = 0 AND @RecKey1 <> 0
					SELECT	OrgKey, RecFld
					FROM	qry_hp_ObjSource_sub
					WHERE	OrgKey=@RecKey
					ORDER BY NameYur
				IF @RecKey <> 0 AND @RecKey1 <> 0
					SELECT	OrgKey, RecFld
					FROM	qry_hp_ObjSource_sub
					WHERE	OrgType=@RecKey AND OrgKey = @RecKey1
					ORDER BY NameYur								
			END
		ELSE
			BEGIN
				IF CHARINDEX(N'NOTIN', @RecKeyList) > 0
					BEGIN
						SET @DopWhere = SUBSTRING(@RecKeyList, 7, Len(@RecKeyList));
						SELECT	OrgKey, RecFld
						FROM	qry_hp_ObjSource_sub
						WHERE	OrgType NOT IN(SELECT number FROM dbo.iter_intlist_to_table(@DopWhere))
						ORDER BY NameYur
					END					
				ELSE
					IF CHARINDEX(N'IN', @RecKeyList) > 0
						BEGIN
							SET @DopWhere = SUBSTRING(@RecKeyList, 3, Len(@RecKeyList));
							SELECT	OrgKey, RecFld
							FROM	qry_hp_ObjSource_sub
							WHERE	OrgType IN(SELECT number FROM dbo.iter_intlist_to_table(@DopWhere))
							ORDER BY NameYur
						END									
			END
	END


Я тут начал изворачиваться через комбинации параметров, чтобы через одну вьюху и хранимку создать источники для нескольких списков, использующих одну таблицу, но с разными фильтрами. А по твоим рассуждениям надо каждому списку свою хранимку - чтобы получить максимальную скорость. Ну допустим.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115431
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Натыкался еще на такой способ "уменьшения кол-во объектов на сервере" - использование .NextRecordset. То есть пишется хранимка с несколькими селектами, а спискам в той же последовательности присваиваются через .NextRecordset источники. Понятно, что опять рефлексия минимизации - а скорость будет такая же как при отдельных хранимках или ниже?

Shocker.ProДанный подход имеет и побочный эффект: можно модернизировать хранилище, не переписывая клиента и/или сохранять совместимость со старыми версиями. Это особенно удобно, если клиентов много и взять и резко обновить всем версию клиента представляется затруднительным. Просто в новой версии обращаешься к тем же данным по-новому (новая хранимка или новые параметры хранимки, имеющие значения по умолчанию), старые клиенты продолжают работать по-старомуМне твой совет по переносу всех селектов на сервер толкнул еще одну мысль - проще будет сменить платформу клиента. Не век же на Аксесе лабать. + возможность развернуть целую сетку клиентских приложений на смартфонах, планшетах и т. п. юзающих одну БД + возможность параллельной разработки БД и клиента, как в web: дизайнер + программист.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115438
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Palarm
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
				IF @RecKey <> 0 AND @RecKey1 = 0
					SELECT	OrgKey, RecFld
					FROM	qry_hp_ObjSource_sub
					WHERE	OrgType=@RecKey
					ORDER BY NameYur
				IF @RecKey = 0 AND @RecKey1 <> 0
					SELECT	OrgKey, RecFld
					FROM	qry_hp_ObjSource_sub
					WHERE	OrgKey=@RecKey
					ORDER BY NameYur
				IF @RecKey <> 0 AND @RecKey1 <> 0
					SELECT	OrgKey, RecFld
					FROM	qry_hp_ObjSource_sub
					WHERE	OrgType=@RecKey AND OrgKey = @RecKey1
					ORDER BY NameYur	

просто, если немножко подумать, то:
Код: sql
1.
2.
3.
4.
5.
SELECT	OrgKey, RecFld
FROM	qry_hp_ObjSource_sub
WHERE	(@RecKey = 0 OR OrgType = @RecKey) AND
        (@RecKey1 = 0 OR OrgKey = @RecKey1)
ORDER BY NameYur



что касается [NOT] IN - то тут делается инлайн-функция для повторяющегося кода, а where и order остаютс в процедуре, но тот всего два варианта ведь, а не сотня
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115440
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PalarmНатыкался еще на такой способ "уменьшения кол-во объектов на сервере" - использование .NextRecordset. То есть пишется хранимка с несколькими селектами, а спискам в той же последовательности присваиваются через .NextRecordset источники. Понятно, что опять рефлексия минимизации - а скорость будет такая же как при отдельных хранимках или ниже?тут, в общем-то, идет минимизация обращений к серверу. То есть используя возврат нескольких рекордсетов ты экономишь на накладных расходах установки соединения и отсылке запроса к серверу. При медленном соединении и интенсивных запросах на этом можно сэкономить. Но у меня, к примеру, в проекте с полутора тысячью хранимок этот прием используется дай бог в десятке.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115449
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Palarmпроще будет сменить платформу клиента. Не век же на Аксесе лабать. + возможность развернуть целую сетку клиентских приложений на смартфонах, планшетах и т. п. юзающих одну БД + возможность параллельной разработки БД и клиента, как в web: дизайнер + программист.Тогда во-первых смотри на трехзвенную архитектуру: СУБД, сервер приложения и клиент. При этом клиент в таком случае не то что об SQL, вообще о БД не имеет никакого понятия. Он обращается к серверу приложений за высокоуровневыми функциями.

Но тут уже смотри... Последнее время есть тенденция использовать ORM. Это означает в основном отказ от языка SQL. Тут свои достоинства и недостатки, споров много, в основном переход на ORM считается прогрессивным. Я одно приложение наваял не очень нагруженное - да - удобно, но надо опять сильно перестраивать мозг.
Вообще, выбор платформы, это тема бесконечной дискуссии ))
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115571
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо за помощь :)

Еще вопрос: есть много таких блоков
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
If sLookup("SELECT COUNT(OrgKey2) AS ReCnt FROM tab_Org WHERE OrgKey=" & Me.OrgKey1) > 0 Then
    If MsgBox("бла бла бла?", vbExclamation + vbYesNo + vbDefaultButton2, NomWers) = vbNo Then
        Exit Sub
    Else
        con.Execute "hp_InsertZakazIsp " & Me.TTD_ID & "," & Me.OrgKey1 & "," & Me.Zak_ID
    End If
End If


тут видится 2 варианта:
1. сделать udf возвращающей bit и в зависимости от него запускать мессагу (но опять же - как гвоздем по стеклу - лепить кучи одностроковых функций - эх)
2. вставить проверку в хранимку - делать прерывание - отсылать клиенту код - ждать ответа - продолжать или закрывать выполнение. Но тут походу кощунство для T-SQL адептов - попытка внедрить процедурное мышление :) Да и навряд ли T-SQL поддерживает такие пинг-понги с клиентом, по крайней мере я не встречал примеров.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115601
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Во-первых, открой для себя Exists, это будет быстрее, чем Count>0

Во-вторых, проблему диалога с пользователем я лично для себя решил следующим образом. Дано - хранимка может выполнить задачу, либо вернуть ошибку, либо вернуть запрос на подтверждение пользователем продолжения работы хранимки (таких запросов может быть N).

Хранимка возвращает >=0 при успешном выполнении, -1, если ошибка без возможности продолжения, -2 запрос к пользователю на возможность продолжения. Поскольку подтверждений может быть несколько, ответ циклически накапливается в Confirm, текст ошибки или подтверждения в ErrMsg. В хранимке:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
CREATE PROCEDURE MyProc
......
@ErrMsg$ nvarchar(1000)=N'' OUTPUT,
@Confirms$ nvarchar(1000)=N'' OUTPUT
AS

if (критическое_условие) begin
  set @ErrMsg$=N'Текст ошибки.'
  return -1
end

if charindex(N'MYKEY1$',@Confirms$)=0 begin
  if (проверка_некритичного_условия) begin
    set @ErrMsg$=N'Текст подтверждения для клиента'
    set @Confirms$=@Confirms$+N'MYKEY1$'
    return -2
  end
end

--основные действия процедуры

то есть в @Confirms$ накапливаются подтверждения пользователя типа N'MYKEY1$N'DELETE$EMPTYNAME$' и т.п. по количеству проверок.

на клиенте
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Dim ErrMsg As String, Confirms As String

rep:
Select Case вызов_хранимки(.........., "@ErrMsg$", ErrMsg, "@Confirms$", Confirms)
  Case 0
    'действия при успешном выполнении
  Case -1
    MsgBox ErrMsg, vbCritical, "Заголовок"
  Case -2
    If MsgBox(ErrMsg + vbCr + "Продолжить?", vbExclamation + vbYesNo, "Заголовок") = vbYes Then GoTo rep
End Select


или
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Dim ErrMsg As String, Confirms As String

rep:
Select Case вызов_хранимки(.........., "@ErrMsg$", ErrMsg, "@Confirms$", Confirms)
  Case -1
    MsgBox ErrMsg, vbCritical, "Заголовок"
    Exit Sub
  Case -2
    If MsgBox(ErrMsg + vbCr + "Продолжить?", vbExclamation + vbYesNo, "Заголовок") = vbYes Then GoTo rep
    Exit Sub
End Select
'действия при успешном выполнении
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115624
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Стало быть повторный вызов с обновленным параметром, причем если через return то придется запускать через cmd.Parameters.Append cmd.CreateParameter("RETURN_VALUE", adInteger, adParamReturnValue). А если как мне больше нравится через con - тогда свой Output параметр туда вводить.
Спасибо за наводку.
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115629
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PalarmСтало быть повторный вызовда. Ведь надо понимать, что пользователь может думать час над мессаджбоксом, за это время в базе может много чего измениться. То есть все проверки каждый раз проводятся заново - во избежание...
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39115666
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Наваял, работает, причем всем назло через con.Execute, а не cmd.Parameters :)
Было:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
Function funInsertDopKod(ByVal Kart_ID As Long, ByVal UKT_ID As Long) As Boolean
Dim flg_Trans As Boolean

On Error GoTo Err_
    If Nz(sLookup("SELECT Count(*) AS RecCnt FROM tab_UKT_ZED_DopKodInvois WHERE UKT_ID=" & UKT_ID), 0) = 0 Then
        If Nz(sLookup("SELECT Count(*) AS RecCnt FROM tab_MKart_DopKodInvois WHERE Kart_ID=" & Kart_ID), 0) > 0 Then
            If MsgBox("Для обраного коду УКТ ЗЕД відсутні дані по додатковим кодам в Електронний Інвойс, 
але додаткові коди з іншого коду УКТ ЗЕД вже присутні в картці товару. Видалити їх?", 
vbExclamation + vbYesNo + vbDefaultButton2, NomWers) = vbNo Then Exit Function
            con.Execute "Delete From tab_MKart_DopKodInvois Where Kart_ID=" & Kart_ID
            funInsertDopKod = True
        End If
    Else
        If MsgBox("Присутні дані по додатковим кодам в Електронний Інвойс. Додати їх в картку товару? Попередні дані будуть видалені.",
 vbExclamation + vbYesNo + vbDefaultButton2, NomWers) = vbNo Then Exit Function
'***************<Начало транзакции>********************
        con.BeginTrans
        flg_Trans = True
        
        con.Execute "Delete From tab_MKart_DopKodInvois Where Kart_ID=" & Kart_ID
        con.Execute _
            "Insert Into tab_MKart_DopKodInvois(Kart_ID, DK_ID) " & _
            "SELECT " & Kart_ID & ",DK_ID " & _
            "FROM   tab_UKT_ZED_DopKodInvois " & _
            "WHERE  UKT_ID=" & UKT_ID

        con.CommitTrans
        flg_Trans = False
'***************<Конец/ транзакции>********************
        funInsertDopKod = True
    End If
Exit Function

Err_:
    If flg_Trans = True Then con.RollbackTrans
    Call ErrorBases(Err, "mdl_FormFun", "InsertDopKod")
End Function


Стало
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
Function funInsertDopKod(ByVal Kart_ID As Long, ByVal UKT_ID As Long) As Boolean
Dim Result As Integer
Dim rs As ADODB.Recordset
Dim sErrMsg As String, sConfirms As String

On Error GoTo Err_
    Set rs = New ADODB.Recordset
lab:
    Set rs = con.Execute( _
            "USE tam;" & _
            "DECLARE @ErrMsg nvarchar(1000)='" & sErrMsg & "',@Confirms nvarchar(1000)='" & sConfirms & "',@Result INT;" & _
            "EXECUTE hp_InsertDopKod " & Kart_ID & "," & UKT_ID & ",@ErrMsg OUTPUT,@Confirms OUTPUT,@Result OUTPUT;" & _
            "SELECT @ErrMsg AS Cnt;SELECT @Confirms AS Cnt;SELECT @Result AS Cnt")
    sErrMsg = Nz(rs.NextRecordset.Fields(0).Value, "")
    sConfirms = Nz(rs.NextRecordset.Fields(0).Value, "")
    Result = Nz(rs.NextRecordset.Fields(0).Value, 0)
    
    Select Case Result
      Case -1
        MsgBox sErrMsg, vbCritical, NomWers
        Exit Function
      Case -2
        If MsgBox(sErrMsg, vbExclamation + vbYesNo, NomWers) = vbYes Then GoTo lab
    End Select
    funInsertDopKod = True
Exit Function

Err_:
    Call ErrorBases(Err, "mdl_FormFun", "InsertDopKod")
End Function


И на серваке
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
ALTER PROCEDURE [dbo].[hp_InsertDopKod]
	@Kart_ID INT,
	@UKT_ID INT,
	@ErrMsg nvarchar(1000)=N'' OUTPUT,
	@Confirms nvarchar(1000)=N'' OUTPUT,
	@Result INT OUTPUT
AS
 
BEGIN
	SET NOCOUNT ON;

	IF NOT EXISTS(SELECT * FROM tab_UKT_ZED_DopKodInvois WHERE UKT_ID=@UKT_ID)
		IF EXISTS(SELECT * FROM tab_MKart_DopKodInvois WHERE Kart_ID=@Kart_ID) 
			IF CHARINDeX(N'check1', @Confirms) = 0 
				BEGIN
					SET @ErrMsg = 'Для обраного коду УКТ ЗЕД відсутні дані по додатковим кодам в Електронний Інвойс,
 але додаткові коди з іншого коду УКТ ЗЕД вже присутні в картці товару. Видалити їх?'
					SET @Confirms = @Confirms + N'check1'
					SET @Result = -2
				END
			ELSE
				DELETE FROM tab_MKart_DopKodInvois WHERE Kart_ID=@Kart_ID
	ELSE
		IF CHARINDeX(N'check2', @Confirms) = 0
			BEGIN			
				SET @ErrMsg = 'Присутні дані по додатковим кодам в Електронний Інвойс. 
Додати їх в картку товару? Попередні дані будуть видалені.'
				SET @Confirms = @Confirms + N'check2'
				SET @Result = -2
			END
		ELSE
			BEGIN
				BEGIN TRY
					BEGIN TRANSACTION
						DELETE FROM tab_MKart_DopKodInvois WHERE Kart_ID=@Kart_ID;
						INSERT INTO tab_MKart_DopKodInvois(Kart_ID, DK_ID)
						SELECT @Kart_ID, DK_ID
						FROM   tab_UKT_ZED_DopKodInvois
						WHERE  UKT_ID=@UKT_ID;
					COMMIT TRANSACTION
				END TRY
				BEGIN CATCH
					ROLLBACK
					SET @ErrMsg = 'Произошел откат транзакции';
					THROW
					SET @Result = -1
				END CATCH
			END
END
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39118117
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: vbnet
1.
If (Условие)=0 Then Exit Sub

Предполагаю, что аналога именно такого прерывания нет в T-SQL, а нужно делать как в вышеприведеных примерах - отсылать клиенту код ошибки и там уже принимать решение - перезапускать выполнение хранимки или нет. Правильно?
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39118130
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PalarmПредполагаю, что аналога именно такого прерывания нет в T-SQLчем не нравится return?
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39118153
Фотография Palarm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще то да. Тогда еще вопрос: есть ли возможность организовать индикацию процесса выполнения хранимки? Имеется в виду отдельная форма с бегунком. Тут ведь по любому придется делать множество перезапусков хранимки, чтобы вернуть текущее состояние процесса и отразить его для пользователя.
Оно понятно, что на сервере надо стараться работать с блоками данных, а не циклами, и по большому счету от бегунка кроме лишних тормозов толку особого нет - но из любопытства: может есть какой progressbar в T-sql или какой то маневр, чтобы его запустить на клиенте?
...
Рейтинг: 0 / 0
Результат хранимки через ADO
    #39118236
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, есть, в FAQ посмотри
...
Рейтинг: 0 / 0
47 сообщений из 47, показаны все 2 страниц
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Результат хранимки через ADO
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]