如何仅保留某个数据库的 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 中为多个参数设置值

尝试运行 alter session 命令以通过 JDBC 设置会话变量

Oracle-Alter-Session

部分删除/销毁 $_SESSION 数据? PHP

Oracle:如何确定“AFTER ALTER”触发器中对象的新名称?