上下文切换—EXECUTE AS 与 SETUSER的使用

本文对比了EXECUTEAS和SETUSER两种上下文切换功能的优缺点,并详细阐述了它们在权限管理、作用范围及恢复上下文方面的差异。通过具体实例展示了如何使用这两种语句。
都有切换上下文的功能

[color=blue]一、比较上下文切换功能:[/color]
与 SETUSER 语句相比,EXECUTE AS 具有以下优点:
1、除 sa 和 dbo 之外的服务器主体或数据库主体可以调用 EXECUTE AS。
1)、调用 EXECUTE AS 语句的用户必须具有目标主体的 IMPERSONATE 权限。
2)、SETUSER 只限制于 sysadmin 固定服务器角色的成员或 db_owner 固定数据库角色的成员。

2、在语句中显式定义模拟的作用域。
1)、将指定的主体指定为 LOGIN(服务器级模拟),或者指定为 USER(数据库级模拟)。
2)、SETUSER 语句中的模拟作用域是隐式的。如果 sysadmin 的成员调用该语句,将使用服务器级模拟。如果为 dbo 的帐户调用该语句,将使用数据库级模拟。

3、模拟将保持有效,直到出现下列情况之一为止:
1)、删除会话。
2)、上下文被切换到另一登录名或用户。
3)、上下文被恢复到以前的执行上下文。
对于 SETUSER,模拟将保持有效,直到出现下列情况之一为止
1)、发出另一个 SETUSER 语句。
2)、当前数据库由为 dbo 的帐户或为 sysadmin 固定服务器角色成员的帐户使用 USE 语句更改。

[color=blue]二、恢复到以前的上下文[/color]
[color=green]1、EXECUTE AS[/color]
使用 REVERT 语句可以返回到以前的上下文。REVERT 语句的调用方必须位于发生模拟的数据库中。
[color=green]2、SETUSER[/color]
若要返回到以前的上下文,请使用 SETUSER 语句且不指定用户名。

[color=blue]三、实例[/color]
[color=green]1、EXECUTE AS[/color]
USE Sales;
GO
CREATE PROCEDURE dbo.usp_Demo
WITH EXECUTE AS 'CompanyDomain\SqlUser1'
AS
SELECT user_name();
GO

[color=green]2、SETUSER[/color]
SETUSER 'mary'
GO
GRANT SELECT ON computer_types TO joe
GO
SETUSER
### 使用SQLAlchemy实现动态切换数据库的功能 为了实现通过 SQLAlchemy 动态切换数据库的功能,可以采用多种方式。以下是基于引用中的内容以及常见实践的一种解决方案。 #### 1. 定义多个引擎并动态绑定会话 可以通过创建多个 `Engine` 对象,并将其动态绑定到 `Session` 中来实现数据库的动态切换功能。这种方式适用于需要在同一应用中操作多个数据库的情况。 ```python from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker, scoped_session from sqlalchemy.ext.declarative import declarative_base # 声明基础类 Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String(50), nullable=False) email = Column(String(120), unique=True, nullable=False) # 创建不同的数据库连接字符串 db_config_1 = 'sqlite:///database1.db' # 数据库1配置 db_config_2 = 'sqlite:///database2.db' # 数据库2配置 # 初始化两个 Engine 实例 engine_db1 = create_engine(db_config_1) engine_db2 = create_engine(db_config_2) # 创建一个通用的 Session 工厂 SessionFactory = sessionmaker() session = scoped_session(SessionFactory) def set_bind(engine_name): """设置当前会话使用的数据库""" if engine_name == 'db1': session.configure(bind=engine_db1) elif engine_name == 'db2': session.configure(bind=engine_db2) else: raise ValueError("Invalid database name") # 示例:动态切换数据库 set_bind('db1') # 切换到数据库1 print(f"Current bound engine: {session.bind}") # 输出当前绑定的引擎 set_bind('db2') # 切换到数据库2 print(f"Current bound engine: {session.bind}") # 输出当前绑定的引擎 ``` 此代码片段展示了如何通过更改 `bind` 参数来动态切换数据库[^1]。 --- #### 2. 在 Flask 应用中实现动态切换数据库 如果是在 Flask 环境下开发,则可以扩展上述逻辑,在每次请求时根据需求动态切换数据库模式或连接。 以下是一个完整的 Flask 示例: ```python from flask import Flask from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy.ext.declarative import declarative_base app = Flask(__name__) Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String(50), nullable=False) email = Column(String(120), unique=True, nullable=False) # 配置多个数据库连接 DATABASE_CONFIGS = { 'default': 'sqlite:///default.db', 'secondary': 'sqlite:///secondary.db' } engines = { db_name: create_engine(url) for db_name, url in DATABASE_CONFIGS.items() } sessions = {} for db_name, engine in engines.items(): sessions[db_name] = scoped_session(sessionmaker(bind=engine)) @app.route('/switch/<string:db>') def switch_database(db): try: current_session = sessions.get(db) if not current_session: return f"No such database configured: {db}", 400 result = current_session.query(User).all() return str(result) except Exception as e: return f"Error occurred while querying the database: {e}", 500 if __name__ == '__main__': app.run(debug=True) ``` 在此示例中,Flask 路由 `/switch/<string:db>` 接收参数 `db` 来决定使用哪个数据库执行查询操作[^3]。 --- #### 3. 动态修改 Schema 或 Mode (针对支持 Schema 的数据库如 PostgreSQL 和 Oracle) 对于某些支持 Schema 的数据库(例如 PostgreSQL),还可以通过 SQL 查询语句临时改变当前会话的工作 Schema。 ```python def change_schema(schema_name, session): """更改当前会话的 schema""" session.execute(f'SET search_path TO {schema_name}') session.commit() change_schema('jack', session) # 将工作模式更改为 jack ``` 这种技术特别适合于像达梦数据库这样的场景,其中用户可能拥有多个模式[^3]。 --- ### 总结 以上介绍了三种主要的方法用于实现 SQLAlchemy 下的动态数据库切换功能: - **多引擎绑定**:通过调整 `Session` 的 `bind` 属性完成。 - **Flask 上下文管理**:利用 Flask 请求上下文中传递的信息控制具体要访问的数据库实例。 - **Schema 修改**:直接运行 SQL 更改当前会话的作用域至目标 Schema。 这些方法可以根据实际项目需求灵活组合运用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值