简体   繁体   English

从 MS Access VBA 前端在 SQL 中使用 SESSION_CONTEXT

[英]Using SESSION_CONTEXT in SQL from an MS Access VBA frontend

I am migrating a MS Access back end database into SQL server.我正在将 MS Access 后端数据库迁移到 SQL 服务器。

The existing MS Access front end needs to be be retained.需要保留现有的 MS Access 前端。

I am connecting the Access front-end to the SQL database using a service account so that individual users have no direct access to SQL.我使用服务帐户将 Access 前端连接到 SQL 数据库,以便单个用户无法直接访问 SQL。

I want to record UserId's on record Add and Update actions, but I do not want to have to specify the fields on every call.我想记录 UserId 的添加和更新操作,但我不想在每次调用时都指定字段。

I have a hidden table open in Access to maintain a persistent connection to the SQL database.我在 Access 中打开了一个隐藏表,以保持与 SQL 数据库的持久连接。

I created a Session Context object with the UserId in Access using a Sub I call on Access startup, and I have even called the Sub directly before running the record insert.我使用 Access 启动时调用的 Sub 在 Access 中创建了一个带有 UserId 的 Session Context 对象,我什至在运行记录插入之前直接调用了 Sub。

Sub SqlSetUser()
Dim qdef As DAO.QueryDef

Set qdef = CurrentDb.CreateQueryDef("")
qdef.Connect = CurrentDb.TableDefs("dbo_User").Connect
qdef.SQL = "EXEC sys.sp_set_session_context @key = N'UserId', @value = '" & GetUser() & "';"
qdef.ReturnsRecords = False  ''avoid 3065 error
qdef.Execute

End Sub

I created a trigger in a SQL table to extract the UserId and add it to the record being added with a similar trigger to handle updates;我在 SQL 表中创建了一个触发器来提取 UserId 并将其添加到使用类似触发器添加的记录中以处理更新;

CREATE   TRIGGER [dbo].[ReferenceItemAdd]
on [dbo].[ReferenceItem]
FOR INSERT
AS
BEGIN
    SET NOCOUNT ON;
    declare @UserId as int = try_cast((Select SESSION_CONTEXT(N'UserId')) as int)
    UPDATE ReferenceItem set AddDate = getdate(), AddUserId = @UserId
    from INSERTED i, ReferenceItem a
    where i.ReferenceItemId = a.ReferenceItemId
    SET NOCOUNT OFF;
END

It only works if I stop the code via a breakpoint and then continue .仅在我通过断点停止代码然后继续时才有效 If I allow the code to run the record is inserted, and the AddDate is set correctly by the trigger but the UserId comes back with NULL.如果我允许代码运行,则插入记录,并且触发器正确设置了 AddDate,但 UserId 返回 NULL。

How can the UserId be made accessible for a trigger in MS-SQL from an MS-Access front-end?如何从 MS-Access 前端为 MS-SQL 中的触发器访问 UserId?

I don't grasp your notes about increased security here?我不明白你关于提高安全性的笔记?

If you have a client web browser, and a web server, then you certainly have a web server that can update the SQL database with a service account because you have a WHOLE web server between the client and the SQL database.如果您有一个客户端 Web 浏览器和一个 Web 服务器,那么您当然有一个可以使用服务帐户更新 SQL 数据库的 Web 服务器,因为在客户端和 SQL 数据库之间有一个完整的 Web 服务器。

You have NONE of the above.您没有上述任何一项。

Eg:例如:

qdef.Connect = CurrentDb.TableDefs("dbo_User").Connect
qdef.SQL = "EXEC 

Right, so you have linked tables and above is a connection string that is directly hitting the database, and even able to execute stored procedures.对,所以你有链接表,上面是一个直接命中数据库的连接字符串,甚至可以执行存储过程。 I assume this connection is the SAME one used by the linked tables?我假设此连接与链接表使用的连接相同? (anyway, we can leave the supposed security issue for another day – what you have here is plane jane linked tables, and they are directly updating the database, and even able to execute stored procedure code as per your above example. (无论如何,我们可以把所谓的安全问题留待一天——你这里有的是平面 jane 链接表,它们直接更新数据库,甚至能够按照上面的例子执行存储过程代码。

Next up:接下来:

We assume one SQL logon is being used here?我们假设这里使用了一个 SQL 登录?

Your code should work, what looks wrong is this:你的代码应该可以工作,看起来不对的是:

declare @UserId as int = try_cast((Select SESSION_CONTEXT(N'UserId')) as int)

Why are you casting the above to a int?你为什么将上述内容转换为 int? Is not GetUser() you set a string?你不是GetUser()设置了一个字符串吗? (your example code has ' ' around the text – so it assumed to be a character type. (您的示例代码在文本周围有 ' ' - 因此它假定为字符类型。

And it is a direct variable assignment – you don't need the select.它是一个直接的变量赋值——你不需要选择。

You should be using:你应该使用:

 DECLARE @UserID as varchar(25) = CAST(SESSION_CONTEXT(N'UserId') AS varchar(25))

I don't know if the session will remain constant for all the linked tables.我不知道所有链接表的会话是否会保持不变。 I would 100% ensure that all linked tables have the exact same connection string.我会 100% 确保所有链接表都具有完全相同的连接字符串。 You should be able to execute your code one time on startup to set that session value.您应该能够在启动时执行一次代码以设置该会话值。 However, I not 100% sure that a single session will always be used here (you can come back and confirm this - as I am rather interested if this is the case).但是,我不能 100% 确定这里将始终使用单个会话(您可以回来确认这一点 - 如果是这种情况,我很感兴趣)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM