如何仅为特定数据库保留Alter Session Set变量?

时间:2011-11-08 14:53:43

标签: oracle

我想将每个查询的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世界中,我的意思是“架构”/“用户”。

2 个答案:

答案 0 :(得分:3)

您可以在

上创建触发器
  • 数据库启动或实例关闭
  • 用户登录或注销

http://download.oracle.com/docs/cd/B14117_01/server.101/b10743/triggers.htm#i6061

答案 1 :(得分:1)

首先,您能否澄清“数据库”的含义?在Oracle术语中,数据库是受ALTER SYSTEM调用影响的模式集。可以在单个服务器上拥有多个数据库,但在计算机上只能有一个XE数据库。如果您来自SQL Server后台,那么SQL Server称之为“数据库”的内容与Oracle称之为“模式”的内容更为相似。

假设你真的是指架构而不是数据库,并且假设Oracle CASETEST用户只与一个架构中的表进行交互,我会在第二个bpgergo中建议CASETEST架构中的登录触发器。