Гость
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Двойное обращение к хранимке на MS SQL сервере. Это лечится... / 3 сообщений из 3, страница 1 из 1
16.06.2020, 09:18
    #39969588
Диам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Двойное обращение к хранимке на MS SQL сервере. Это лечится...
Тут описание косяка Акцесса. Двойное обращение к хранимке на MS SQL сервере. В конце описан обход этой проблемы.

Для воспроизведения:

Особенности Акцесса
'пример, демонстрирующий, что открытие рекордсета с запросом в виде "SELECT .. FROM sql_запрос", который обращается к хранимой процедуре, вызовет эту хранимку ДВАЖДЫ
'Возможно, что аналогично происходит не только с обращением к хранимке, но и с любым SELECT`ом
'В приведенном примере после каждого вызова в таблицу добавляется 2 записи, хотя в хранимке происходит добавление только одной записи
'При этом вывод результатов происходит именно для результата первого запуска хранимки, а не второго.

На MS SQL сервере выполняем
1.Создаем таблицу
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE TABLE [dbo].[_ttt](
	[ffrom] [nvarchar](128) NULL,
	[dtCrt] [datetime] NULL,
	[kdz] [int] NULL
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[_ttt] ADD  CONSTRAINT [DF__ttt_dtCrt]  DEFAULT (getdate()) FOR [dtCrt]
GO



2. Создаем хранимку
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
CREATE PROCEDURE _TmpTest
AS
BEGIN
	-- exec _TmpTest
	-- select * from [_ttt] order by dtcrt
	--delete from [_ttt]
	
	SET NOCOUNT ON;
  INSERT INTO [_ttt]([kdz])
  values (1)
  
  select COUNT(*)as cnt from [_ttt]
END
GO
grant execute on _TmpTest TO Public
GO



3. В базе Акцесс создаем процедуру обновления sql-запроса
Код: 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.
Public Function editSQLquery(QName As String, stSQL As String, Optional TimeOut As Long = 60) As Boolean

  Dim dbsTMP As DAO.database
  Dim qdfTMP As DAO.QueryDef
  On Error GoTo ErrHandler
  Const prcName As String = "editSQLquery"
  del_tmp_tbl_all
  
  Set dbsTMP = CurrentDb
  Set qdfTMP = dbsTMP.QueryDefs(QName)
  qdfTMP.sql = stSQL
  qdfTMP.ODBCTimeout = TimeOut
  Debug.Print stSQL

Success:
  editSQLquery = True

mEx:
    Set qdfTMP = Nothing
    Set dbsTMP = Nothing
    Exit Function

ErrHandler:
  msgbox Err.Description 'ErrorSave mdlName, prcName, Err.number, "(" & Err.Description & ")" & vbCrLf & "в процедуре " & prcName & " of Module " & mdlName, stSQL
  Resume mEx
  Resume
End Function



4. В БД Акцесс создаем процедуры для теста
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Public Function tmpTest() As Long
  Dim rst As DAO.Recordset
  'пример, демонстрирующий, что открытие рекордсета с запросом в виде "SELECT .. FROM запрос", который обращается к хранимой процедуре, вызовет эту хранимку дважды
	'Возможно, что аналогично происходит не только с обращением к хранимке, но и с любым SELECT`ом
  'В приведенном примере после каждого вызова в таблицу добавляется 2 записи, хотя в хранимке происходит добавление только одной записи
  'При этом вывод результатов происходит именно для результата первого запуска хранимки, а не второго.
  editSQLquery "sql_Any", "exec _TmpTest"
  
  Set rst = CurrentDb.OpenRecordset("SELECT * FROM sql_Any", dbOpenSnapshot)
  'После этого вызова в базе уже 2 строки в таблице [_ttt], а рекордсет вернет значение 1. После следующего вызова он вернет значение 3, потом 5

  If rst.RecordCount <= 0 Then
    MsgBox "Нет данных!", vbExclamation, NameApp
    Exit Function
  End If
  Debug.Print rst!Cnt
End Function



и

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Public Function tmpTest2() As Long
  Dim sql As String, NeedVozvr As Boolean, N As Long
  Dim rst As DAO.Recordset

  editSQLquery "sql_Any", "exec _TmpTest"
  
  'А вот такое обращение выполнит хранимку один раз
  Set rst = CurrentDb.OpenRecordset("sql_Any", dbOpenSnapshot)
  If rst.RecordCount <= 0 Then
    MsgBox "Нет данных!", vbExclamation, NameApp
    Exit Function
  End If
  Debug.Print rst!Cnt
End Function
...
Рейтинг: 0 / 0
16.06.2020, 17:57
    #39969870
Сергей Лалов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Двойное обращение к хранимке на MS SQL сервере. Это лечится...
Диам,
Так не обязательно открывать рекордсет, чтобы выполнить хранимку. Можно просто передать параметры в хранимку ( при необходимости) и выполнить execute её.
...
Рейтинг: 0 / 0
16.06.2020, 19:14
    #39969916
Диам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Двойное обращение к хранимке на MS SQL сервере. Это лечится...
Сергей Лалов
Диам,
Так не обязательно открывать рекордсет, чтобы выполнить хранимку. Можно просто передать параметры в хранимку ( при необходимости) и выполнить execute её.



А как вы хотите получить обратно результат? Приведите пример.
Если что - я про accde или mde говорю. Не про adp
...
Рейтинг: 0 / 0
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Двойное обращение к хранимке на MS SQL сервере. Это лечится... / 3 сообщений из 3, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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