如何仅保留某个数据库的 Alter Session Set 变量?
Posted
技术标签:
【中文标题】如何仅保留某个数据库的 Alter Session Set 变量?【英文标题】:How can I persist Alter Session Set variables for a certain database only? 【发布时间】:2011-12-24 12:54:36 【问题描述】:我想将每个查询的 NLS_SORT 和 NLS_COMP 参数更改为这个特定的模式,但是这个系统上还有其他用户想要保留原始值,所以使用 ALTER SYSTEM SET 是一个禁忌案子。我也不想将每个查询都更改为这个特定的架构。
有没有办法将这些值放在仅针对此架构的初始化文件中,或者我可以以某种方式添加一个触发器,以在会话启动到此架构时在会话上设置这些值?
我正在运行 Oracle Express 11G R2,该解决方案不需要向后兼容。
我的目标是不必在运行 SELECT-LIKE 语句之前运行 ALTER SESSION SET 行并让它产生两个结果而不是一个。这是我用来检查我真正希望 NLS_COMP 和 NLS_SORT 值具有哪些值的 Java 示例代码:
public class OracleCaseTest
public static void main(String[] args) throws SQLException
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
dataSource.setUsername("CASETEST");
dataSource.setPassword("casetest");
Connection conn = null;
PreparedStatement createStatement = null;
PreparedStatement populateStatement = null;
PreparedStatement comparisonAlterSessionStatement = null;
PreparedStatement sortAlterSessionStatement = null;
PreparedStatement queryStatement = null;
PreparedStatement deleteStatement = null;
ResultSet rs = null;
conn = dataSource.getConnection();
createStatement = conn
.prepareStatement("CREATE TABLE CollationTestTable ( Name varchar(255) )");
createStatement.execute();
try
// comparisonAlterSessionStatement = conn
// .prepareStatement("ALTER SESSION SET NLS_COMP=LINGUISTIC");
// comparisonAlterSessionStatement.execute();
//
// sortAlterSessionStatement = conn.prepareStatement("ALTER SESSION SET NLS_SORT=BINARY_CI");
// sortAlterSessionStatement.execute();
String[] names = "pepe", "pépé", "PEPE", "MEME", "mémé", "meme" ;
for (String name : names)
populateStatement = conn
.prepareStatement("INSERT INTO CollationTestTable VALUES (?)");
populateStatement.setString(1, name);
populateStatement.execute();
queryStatement = conn
.prepareStatement("SELECT Name FROM CollationTestTable WHERE NAME LIKE 'pe%'");
rs = queryStatement.executeQuery();
while (rs.next())
System.out.println(rs.getString(1));
finally
deleteStatement = conn.prepareStatement("DROP TABLE CollationTestTable");
deleteStatement.execute();
我知道在没有语言索引的情况下进行全表扫描可能会产生问题,但请忽略这个问题。
更新:这是我用来从 SQL 命令行界面创建触发器的语句(在连接并登录我的用户之后):
create or replace trigger nls_settings
after logon on schema
begin
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_COMP=LINGUISTIC';
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_SORT=BINARY_CI';
end nls_settings;
/
还更改了原始问题以表明“数据库”在 Oracle 世界中的真正意思是“模式”/“用户”。
【问题讨论】:
【参考方案1】:您可以在
上创建触发器 数据库启动或实例关闭 用户登录或注销http://download.oracle.com/docs/cd/B14117_01/server.101/b10743/triggers.htm#i6061
【讨论】:
试过了,只要我使用的是细连接器,它就可以正常工作。现在我们需要切换到粗连接器 oci8,我们又遇到了这个问题,但只要您使用的是细连接器,我认为这是最简单的解决方法。 如果这对您来说仍然是个问题,那么我建议您提出一个新问题并确保您向 SO 提供以下详细信息:1)您拥有的触发器的来源(并期望触发登录); 2) 您使用 OCI 登录的确切方法(如download.oracle.com/docs/cd/B19306_01/appdev.102/b14250/…,以及源)。 我现在正在与 Oracle 顾问联系,我们正在修改我们的数据源,以便每当获取新连接时,它首先运行 nls_comp 和 nls_sort 命令。【参考方案2】:首先,您能澄清一下“数据库”是什么意思吗?在 Oracle 术语中,数据库是受ALTER SYSTEM
调用影响的模式集。一台服务器上可以有多个数据库,但一台机器上只能有一个 XE 数据库。如果您来自 SQL Server 背景,SQL Server 所称的“数据库”更类似于 Oracle 所称的“架构”。
假设您真正的意思是模式而不是数据库,并假设 Oracle CASETEST 用户只与一个模式中的表交互,我会同意 bpgergo 建议在 CASETEST 模式中使用登录触发器。
【讨论】:
确实,我不得不更新自己的术语,因为 Oracle 数据库对术语模式和数据库使用的含义与其他关系数据库略有不同。我发现这个 SO 问题很有帮助,例如:***.com/questions/880230/… 我的意思实际上是一个模式,因为我认为我们将拥有一个用户下的所有应用程序表。我现在更新了我的问题以反映这一点。以上是关于如何仅保留某个数据库的 Alter Session Set 变量?的主要内容,如果未能解决你的问题,请参考以下文章
找出 alter system kill session ‘sid,serial#’ kill 掉的数据库会话对应进程
Oracle SQL - 在同一个 alter_session_set_clause 中为多个参数设置值