Avatar billede nayze Nybegynder
10. august 2007 - 13:07 Der er 12 kommentarer

Sammenligning af strenge

Jeg har en "NAME_TYPE" der er NVARCHAR2(20) i min names_and_notations tabel, hvor name_type kun kan være PrimaryName eller AlternativeName (hvilket checkes med en check-constraint).

select name_type from names_and_notations where name_id = 0;
NAME_TYPE
--------------------
PrimaryName



Kan nogen så forklare mig, forskellen på de to følgende select-queries:

Select count(*) from names_and_notations where NAME_TYPE = 'PrimaryName';

  COUNT(*)
----------
        0



Select count(*) from names_and_notations where LOWER(NAME_TYPE) = 'primaryname';

  COUNT(*)
----------
      4625



Hvorfor finder NAME_TYPE = 'PrimaryName' lige præcis 0 forekomster?
Avatar billede holdam Nybegynder
10. august 2007 - 14:00 #1
Det ser for mig ud som om der er andet end "PrimaryName" og "AlternativeName" i din tabel. Så måske er din check constraint ikke aktiveret?

Prøv følgende:

SELECT name_type, count(*) FROM names_and_notations GROUP BY name_type;

- det giver lidt information om fordelingen af data i tabellen.
Avatar billede nayze Nybegynder
10. august 2007 - 14:02 #2
SQL> SELECT name_type, count(*) FROM names_and_notations GROUP BY name_type;

NAME_TYPE              COUNT(*)
-------------------- ----------
PrimaryName                4628


Lige nu har jeg kun test-data liggende, og der ved jeg med sikkerhed, at der kun er navne af typen PrimaryName.
Avatar billede holdam Nybegynder
10. august 2007 - 14:39 #3
Det eneste jeg umiddelbart kan komme i tanke om, er at det er Unicode der spøger. Når du definerer kolonnen som NVARCHAR2, gemmes data som Unicode-værdier. Og så ved jeg faktisk ikke om din strengkonstant 'PrimaryName' er i Unicode også - det må afhænge af databasens tegnsæt.

Hvis du har mulighed for det, kan du evt. prøve at definere din kolonne som VARCHAR2 i stedet.

Du kan evt. prøve at lave

SELECT dump(name_type) FROM names_and_notations WHERE ROWNUM=1,

og

SELECT dump('PrimaryName') FROM dual;

for at se om de giver det samme. Men der kan også komme diverse tegnsæt-konverteringer i spil, så selv om de er forskellige, kan Oracle måske godt få dem til at være ens.
Avatar billede holdam Nybegynder
10. august 2007 - 14:44 #4
Jeg faldt over følgende formulering i Oracles dokumentation:

Implicit Conversion Between CHAR/VARCHAR2 and NCHAR/NVARCHAR2

In previous releases (Oracle8i and earlier), the NCHAR and NVARCHAR2 types were difficult to use because they could not be interchanged with CHAR and VARCHAR2. For example, an NVARCHAR2 literal required special notation, such as N'string_value'. Now, you can specify NCHAR and NVARCHAR2 without the N qualifier, and can mix them with CHAR and VARCHAR2 values in SQL statements and functions.

Hvilken version af Oracle bruger du?
Avatar billede nayze Nybegynder
10. august 2007 - 14:56 #5
Ved at lave et par dumps ses en tydelig forskel:

SQL> SELECT dump(name_type) FROM names_and_notations WHERE ROWNUM=1;
DUMP(NAME_TYPE)
----------------------------------------------------------------------------
Typ=1 Len=22: 0,80,0,114,0,105,0,109,0,97,0,114,0,121,0,78,0,97,0,109,0,101

SQL> SELECT dump('PrimaryName') FROM dual;
DUMP('PRIMARYNAME')
------------------------------------------------------
Typ=96 Len=11: 80,114,105,109,97,114,121,78,97,109,101

Dette kan meget vel skyldes unicode-problematikken, som vi også havde overvejet her på stedet.

Databasen er Oracle 10g.
Avatar billede holdam Nybegynder
10. august 2007 - 15:01 #6
Tja - jeg troede så bare at Oracle faktisk konverterede strengene passende - sådan forstår jeg i hvert fald beskrivelsen (hvis char1 og char2 er af hver sin type, konverteres til char1). Det kunne være interessant at lave samme forsøg med "lower"-udgagen.

Men noget rigtigt godt bud på en løsning har jeg vist ikke...
Avatar billede nayze Nybegynder
10. august 2007 - 15:14 #7
Det er helt ok, du skal have tak for hjælpen :]

Det er et lille pudsigt problem, som ikke hindrer mig i mit arbejde, jeg ville bare gerne vide helt hvorfor den opførte sig sådan.
Avatar billede arne_v Ekspert
10. august 2007 - 15:19 #8
Hvad giver:

Select count(*) from names_and_notations where NAME_TYPE = N'PrimaryName';

?
Avatar billede nayze Nybegynder
10. august 2007 - 15:21 #9
Den prøvede jeg også, da holdam skrev kl. 14:44, men den gav desværre ingen forskel. Count er stadigvæk 0.
Avatar billede arne_v Ekspert
27. august 2007 - 05:16 #10
Der er et eller andet mystisk i deit problem:

SQL> CREATE TABLE names_and_notations (name_id INTEGER NOT NULL, name_type NVARCHAR2(20), PRIMARY KEY(name_id));

Tabel er oprettet.

SQL> INSERT INTO names_and_notations VALUES(1,'PrimaryName');

1 række er oprettet.

SQL> INSERT INTO names_and_notations VALUES(2,'SecondaryName');

1 række er oprettet.

SQL> INSERT INTO names_and_notations VALUES(3,'PrimaryName');

1 række er oprettet.

SQL> SELECT COUNT(*) FROM names_and_notations WHERE name_type='PrimaryName';

  COUNT(*)
----------
        2

SQL> SELECT COUNT(*) FROM names_and_notations WHERE name_type=N'PrimaryName';

  COUNT(*)
----------
        2

SQL> DROP TABLE names_and_notations;

Tabel er droppet.

SQL>
Avatar billede arne_v Ekspert
27. august 2007 - 05:16 #11
Dine DUMP's ser ud som forventet.
Avatar billede nayze Nybegynder
27. august 2007 - 12:58 #12
Ja, det er meget mystisk. Vi har netop nu fået problemet igen i en anden tabel ved en anden af vores udviklere. Der går meget forundrelse igennem kontoret :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester