views:

1472

answers:

1

Hi,

I have found this answer useful: Accent and case insensitive COLLATE equivalent in Oracle, but my question is regarding LIKE searching with a version 9 Oracle db.

I have tried a query like this:

SELECT column_name FROM table_name WHERE NLSSORT(column_name, 'NLS_SORT = Latin_AI') LIKE NLSSORT('%somethingInDB%', 'NLS_SORT = Latin_AI')

but no results are ever returned.

I created a little Java file to test:

import org.apache.commons.dbcp.BasicDataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DbCollationTest
{
 public static void main(String[] args) throws SQLException
 {
  BasicDataSource dataSource = new BasicDataSource();
  dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
  dataSource.setUrl("url");
  dataSource.setUsername("usr");
  dataSource.setPassword("pass");

  Connection conn = null;
  PreparedStatement createStatement = null;
  PreparedStatement populateStatement = null;
  PreparedStatement queryStatement = null;
  PreparedStatement deleteStatement = null;
  ResultSet rs = null;

  try
  {
   conn = dataSource.getConnection();

   createStatement = conn.prepareStatement("CREATE TABLE CollationTestTable ( Name varchar(255) )");
   createStatement.execute();

   String[] names = { "pepe", "pépé", "PEPE", "MEME", "mémé", "meme" };
   int i = 1;

   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 NLSSORT(NAME, 'NLS_SORT = Latin_AI') LIKE NLSSORT('%pe%', 'NLS_SORT = Latin_AI')");
   rs = queryStatement.executeQuery();

   while (rs.next())
   {
    System.out.println(rs.getString(1));
   }

   deleteStatement = conn.prepareStatement("DROP TABLE CollationTestTable");
   deleteStatement.execute();
  }
  finally
  {
   //DBTools.tidyUp(conn, null, rs);
   //DBTools.tidyUp(createStatement);
   //DBTools.tidyUp(populateStatement);
   //DBTools.tidyUp(queryStatement);
   //DBTools.tidyUp(deleteStatement);
  }
 }
}

I have not had any success googling, anyone have any solutions?

I want to perform a search on part of a name and return results that are matched using case and accent insensitivity.

Thanks in advance.

+1  A: 

Hi Ed,

one method would be to modify your session parameters NLS_SORT and NLS_COMP:

SQL> SELECT Name FROM CollationTestTable WHERE NAME LIKE '%pe%';

NAME
--------------------------------------------------------------------------------
pepe

SQL> alter session set nls_sort=Latin_AI;

Session altered

SQL> alter session set nls_comp=linguistic;

Session altered

SQL> SELECT Name FROM CollationTestTable WHERE NAME LIKE '%pe%';

NAME
--------------------------------------------------------------------------------
pepe
pépé
PEPE

As shown in another SO, you cannot use the LIKE operator with NLSSORT (this is because, NLSSORT returns a string of bytes that will be used for sorting, and LIKE only works with charater strings)

Update: While setting the NLS parameters would be my first choice, you could also use built-in functions to achieve the same result. A couple of examples:

SQL> SELECT Name
  2    FROM CollationTestTable
  3   WHERE upper(convert(NAME, 'US7ASCII'))
  4         LIKE upper(convert('%pe%', 'US7ASCII'));

NAME
--------------------------------------------------------------------------------
pepe
pépé
PEPE

SQL> SELECT Name
  2    FROM CollationTestTable
  3   WHERE upper(translate(NAME, 'àâéèêìîòôùûÿ', 'aaeeeiioouuy'))
  4         LIKE upper(translate('%pe%', 'àâéèêìîòôùûÿ', 'aaeeeiioouuy'));

NAME
-----------------------------------
pepe
pépé
PEPE
Vincent Malgrat
Thanks for the answer, is there anyway of doing it without altering the session? Other queries in the same session may require the original NLS settings. Cheers.
Ed
@Ed: you could save the session parameters before running the query (select * from nls_session_parameters) then putting them back after the query.
Vincent Malgrat
I have been testing this and all looked good but am now told that NLS_SORT and NLS_COMP solution is only supported in version 10 r2. I need to support Oracle databases with min version 9. Is the only way I can perform the case and accent insensitive search is using functions?
Ed
@Ed: NLS_SORT=linguistic seems to be a 10g feature. You can still use the second method (SQL functions) in 9i.
Vincent Malgrat