Як викликати функцію з ms sql сервера з access
Є програми на 2013 році. Вони прилінковані таблиці з 2008 ms sql сервера. У програмах є форми, де люди редагують дані та зміни за допомогою Update-запитів на прилінковані таблиці зберігаються на сервер. Проблема в тому, що одне з полів має записуватись у зашифрованому вигляді. Наприклад, людина вводить у формі значення 1342, а записатися воно має як Lr$k#yi!&
На ms sql сервері є функції ID_Decrypt, ID_Encrypt (не зберігаються процедури, а, наголошую,скалярні функції), які якраз і займаються цим шифруванням. Приймають один параметр типу varchar, розшифровують\шифрують його і повертають отримане, теж varchar, значення.
Питання у тому, як мені застосувати ці функції до потрібного поля в аксесуарі?
Що я пробував: 1. Робити в аксесуарі passthrough update-запрос. В цьому випадку на незнайому функцію не свариться, отже, бачить. Більше того, якщо не дати вхідний параметр, так і каже, що потрібний параметр; 2. Кодити у VBA через ADO. Використовував штук п'ять різних варіантів, нагуглених на стековерфлоу, жоден не спрацював. Занадто багато варіантів та комбінацій усередині них. Хтось робив через Recordset, хтось через Command + до цього додаються різні варіації виклику функції, а-ля "select ID_Decrypt('1234') as res", "exec ID_Decrypt '123'" та інші з ними.
Якщо можливо у вас завалялсяробочий(тобто. у вас самих він гарантовано працював у схожій ситуації) варіант коду, прошу поділитися.
Помістив у подію "Після оновлення" форми наступний код:
Відповідно, dbo.IDEncrypt – ім'я скалярної функції на ms sql server, а hostel – база даних, в яких ця функція знаходиться. Код точно працює, id зберігається в базузашифрованому вигляді.
Доброго. У такій постановці: 1 варіант простий і не вимагає додаткових рухів тіла. Що в ньому не подобається, навіщо потрібен другий?
Мене особисто бентежить: "до поля в акцесі". А чому, власне, не зробити stored procedure з параметрами, з акцесу формувати рядок, і виконувати взагалі все, а не конкретно апдейт одного поля на стороні сервера?
У першому випадку, хоча запит виконується (принаймні VBA не спотикається на рядку його виклику), зміни не зберігаються. На сервері є таблиця dbo.guest_names, в аксесуарі вона прилінкована під ім'ям dbo_guest_names. Яку треба вказувати? Якщо dbo.guest_names, чи потрібно писати перед ім'ям таблиці ще й ім'я сервера? Загалом у такому вигляді запит бачить лише серверні таблиці або локальні теж? Тобто чи можу я використовувати його для отримання доступу до функцій з ms sql сервера і вставляти оброблені ними дані в локальні таблиці?
Можна і через ХП спробувати. Але тоді мені все одно потрібний приклад, як це технічно правильно реалізувати. Викликати хп із запиту або з VBA і працюючий приклад. Тому що, як я вже казав, приклади зі стековерфлоу не заробили. Можливо, людина побачила там приклад, якось його допрацювала і відзначила рішенням, хоча сам приклад міг бути не до кінця правильним.
Євген: а, тобто. це не ідеологічний підхід. Окей, там усе просто. Ідеологія має бути такою: не потрібно тягати в акцес те, що має виконати на стороні сервера. Тобто. робите сторку, в неї вставляєте вашу функцію, на стороні акцесу: -------- Public Function SQLExecute(QueryText As String) On Error GoTo err
Dim qdf As QueryDef Set qdf = CreateTempQueryDef(QueryText) 'кверидеф з функції повертає записи. qdf.ReturnsRecords = False 'виконали qdf.Execute 'не забули закритися. qdf.Close Exit Function err: MsgBox "Не з'єднуйся з сервером, необхідно зателефонувати за розробником ", vbInformation, "Server error" qdf.Close End Function -- тут потрібно вказати ім'я існуючого проходуза допомогою запиту. -- в нього пишете хоча б select top 1 from mytable і називаєте його RunServerSQLHelper
Private Function CreateTempQueryDef(strSQL As String, Optional strQdfNamePrefix As String = "") As QueryDef ' Dim strQdfName As String If Len(strQdfNamePrefix) > 0 Then strQdfName = RandomName("_" & strQdfNamePrefix) Else 'якщо використовувати таке ім'я то кверідеф буде створено в пам'яті strQdfName = "" End If
Dim qdf As QueryDef Set qdf = CurrentDb. .Connect qdf.SQL = strSQL qdf.ReturnsRecords = True qdf.ODBCTimeout = CurrentDb.QueryDefs("RunServerSqLHelper").ODBCTimeout
'повернув результат Set CreateTempQueryDef = qdf End Function -- 'генерує випадкове ім'я для ацесного об'єкта Public Function RandomName(Optional strPrefix As String = "_tmp") As String
'перевів час з точністю до сотої секунди в рядок Dim strTimeAsString As String strTimeAsString = CStr(Int(CDbl(Now) * 10000000))
'випадковий рядок на випадок, якщо виклики підуть у дуже близький час Dim strRndString As String strRndString = CStr(Int(100000 * Rnd + 1))
' сформував рядок RandomName = strPrefix & "_" & strTimeAsString & "_" & strRndString