:ascii:
n'est pas une classe de caractère valide, et même si elle l'était, il ne semble pas être ce que vous essayez d'obtenir ici (ascii ne contient des caractères non-imprimables). Les classes valides peuvent être trouvées here.
En fait, si vous remplacez :ascii:
par :print:
dans votre requête d'origine, il retournera en effet la première position dans chaque POLINE.DESCRIPTION
qui est un caractère non imprimable. (Si elle ne retourne rien pour vous, il peut être parce que vos données DESCRIPTION
est en fait tout imprimer.)
Mais comme vous l'avez dit vous voulez identifier Chaque omble non imprimable dans chaque DESCRIPTION
dans POLINE
, quelques changements serait nécessaire. Je vais inclure un exemple qui obtient chaque match comme point de départ.
Dans cet exemple, chaque DESCRIPTION
sera décomposé en ses caractères constitutifs individuels, et chaque caractère sera vérifié pour l'imprimabilité. L'emplacement dans la chaîne DESCRIPTION
avec le ASCII number
du caractère non imprimable sera renvoyé.
Cet exemple suppose qu'il existe un identificateur unique pour chaque ligne au POLINE
, appelé ici POLINE_ID
.
Tout d'abord, créez la table de test:
CREATE TABLE POLINE(
POLINE_ID NUMBER PRIMARY KEY,
PONUM VARCHAR2(32),
SITEID VARCHAR2(32),
DESCRIPTION VARCHAR2(256)
);
et charger des données. J'ai inséré quelques caractères non-impression dans l'exemple Sherlock
chaîne que vous avez fourni, #23
et #17
. Un exemple de chaîne composée uniquement des 64 premiers caractères ASCII (dont les 31 premiers ne figurent pas dans :print:
) est également inclus, et certains remplisseurs sont inclus dans les prédicats PONUM
et SITEID
.
INSERT INTO POLINE VALUES (1,'XXX','YYY','Sherlock'||CHR(23)||' 16 x 6.5” Wide Wheelbarrow wheel .M100P.10R –'||CHR(17)||' Effluent care bacteria and enzyme formulation');
DECLARE
V_STRING VARCHAR2(64) := CHR(1);
BEGIN
FOR POINTER IN 2..64 LOOP
V_STRING := V_STRING||CHR(POINTER);
END LOOP;
INSERT INTO POLINE VALUES (2, 'XXX','YYY',V_STRING);
INSERT INTO POLINE VALUES (3, 'AAA','BBB',V_STRING);
END;
/
INSERT INTO POLINE VALUES(4,'XXX','YYY','VOLTRON');
Maintenant, nous avons 4 lignes au total. Trois d'entre eux contiennent (plusieurs) caractères non imprimables, mais seulement deux d'entre eux doivent correspondre à toutes les restrictions.
Ensuite, lancez une requête. Il y a deux exemples de requêtes ci-dessous - le premier utilise REGEXP_INSTR
avec comme dans votre exemple de requête initial (en remplaçant :cntrl:
par :print:
). Mais pour une alternative, une deuxième variante est également incluse qui vérifie simplement si chaque char est dans les 31 premiers caractères ascii.
Les deux exemples de requêtes indexeront chaque caractère de DESCRIPTION
, et vérifieront s'il est imprimable, et collecteront le numéro ASCII et l'emplacement de chaque caractère non imprimable dans chaque candidat DESCRIPTION
. La table d'exemple a ici DESCRIPTION
s qui ont 256 caractères de long, donc ceci est utilisé comme index maximum dans la jointure cartésienne.
S'il vous plaît noter, ce sont pas efficaces, et sont conçus pour obtenir chaque match. Si vous n'avez besoin que de la première correspondance afterall, votre requête originale remplacée par :print:
fonctionnera beaucoup mieux. En outre, cela peut également être réglé en passant dans PL/SOL ou peut-être en se récursif (si PL/SQL est autorisé dans votre cas d'utilisation, ou si vous êtes 11gR2 +, etc.). De plus, certains prédicats tels que REGEXP_LIKE
n'ont pas d'impact sur le résultat final et ne servent qu'à permettre une filtration préliminaire. Ceux-ci pourraient être superflus (ou pire) pour vous, en fonction de votre ensemble de données.
Premier exemple, utilisant l'expression rationnelle et :print:
SELECT
POLINE_ID,
STRING_INDEX AS NON_PRINTABLE_LOCATION,
ASCII(REGEXP_SUBSTR(SUBSTR(DESCRIPTION, STRING_INDEX, 1), '[[:cntrl:]]', 1, 1)) AS NON_PRINTABLE_ASCII_NUMBER
FROM POLINE
CROSS JOIN (SELECT LEVEL AS STRING_INDEX
FROM DUAL
CONNECT BY LEVEL < 257) CANDIDATE_LOCATION
WHERE PONUM = 'XXX'
AND SITEID = 'YYY'
AND REGEXP_LIKE(DESCRIPTION, '[[:cntrl:]]')
AND REGEXP_INSTR(SUBSTR(DESCRIPTION, STRING_INDEX, 1), '[[:cntrl:]]', 1, 1, 0) > 0
AND STRING_INDEX <= LENGTH(DESCRIPTION)
ORDER BY 1 ASC, 2 ASC;
Deuxième exemple, en utilisant les numéros ASCII:
SELECT
POLINE_ID,
STRING_INDEX AS NON_PRINTABLE_LOCATION,
ASCII(SUBSTR(DESCRIPTION, STRING_INDEX, 1)) AS NON_PRINTABLE_ASCII_NUMBER
FROM POLINE
CROSS JOIN (SELECT LEVEL AS STRING_INDEX
FROM DUAL
CONNECT BY LEVEL < 257) CANDIDATE_LOCATION
WHERE PONUM = 'XXX'
AND SITEID = 'YYY'
AND REGEXP_LIKE(DESCRIPTION, '[[:cntrl:]]')
AND ASCII(SUBSTR(DESCRIPTION, STRING_INDEX, 1)) BETWEEN 1 AND 31
AND STRING_INDEX <= LENGTH(DESCRIPTION)
ORDER BY 1 ASC, 2 ASC;
Dans nos données de test, ces requêtes produira une sortie équivalente. Nous devrions nous attendre à ce que cela ait deux hits (pour chrs 17 et 23) dans le Sherlock
DESCRIPTION
, et 31 hits pour le premier-64-ascii DESCRIPTION
.
Résultat:
POLINE_ID NON_PRINTABLE_LOCATION NON_PRINTABLE_ASCII_NUMBER
1 9 23
1 56 17
2 1 1
2 2 2
2 3 3
2 4 4
2 5 5
2 6 6
2 7 7
2 8 8
2 9 9
2 10 10
2 11 11
2 12 12
2 13 13
2 14 14
2 15 15
2 16 16
2 17 17
2 18 18
2 19 19
2 20 20
2 21 21
2 22 22
2 23 23
2 24 24
2 25 25
2 26 26
2 27 27
2 28 28
2 29 29
2 30 30
2 31 31
33 rows selected.
EDIT En réponse aux commentaires, voici quelques précisions sur ce que nous pouvons attendre de [[:cntrl:]]
et [^[:cntrl:]]
avec regexp_instr
.
[[:cntrl:]]
correspond à tout des 31 premiers caractères ascii, alors que [^[:cntrl:]]
est la négation logique de [[:cntrl:]]
, il correspondra tout sauf les 31 premiers caractères ascii.
Pour les comparer, nous pouvons commencer par le cas le plus simple d'un seul caractère, ascii #31
. Comme il n'y a qu'un seul caractère, le résultat ne peut être que match ou miss. On attend ce qui suit pour revenir 1
pour le match:
SELECT REGEXP_INSTR(CHR(31),'[[:cntrl:]]',1,1,0) AS MATCH_INDEX FROM DUAL;
MATCH_INDEX
1
Mais 0 pour la miss avec la négation [^ [: cntrl:]]:
SELECT REGEXP_INSTR(CHR(31),'[^[:cntrl:]]',1,1,0) AS MATCH_INDEX FROM DUAL;
MATCH_INDEX
0
Maintenant, si l'on inclut deux (ou plus) caractères qui sont un mélange de imprimable et non imprimable, il y a plus de résultats possibles. Les deux[[:cntrl:]]
et [^[:cntrl:]]
peuvent correspondre, mais ils ne peuvent correspondre à des choses différentes. Si nous passons seulement de l'ascii #31
à l'ascii #64#31
, nous nous attendons toujours à ce que [[:cntrl:]]
corresponde (puisqu'il y a un caractère non-imprimable dans la deuxième position) mais il devrait maintenant retourner 2, puisque le non-imprimable est dans la deuxième position.
SELECT REGEXP_INSTR(CHR(64)||CHR(31),'[[:cntrl:]]',1,1,0) AS MATCH_INDEX FROM DUAL;
MATCH_INDEX
2
Et maintenant [^[:cntrl:]]
aussi a la possibilité de faire correspondre (à la première position):
SELECT REGEXP_INSTR(CHR(64)||CHR(31),'[^[:cntrl:]]',1,1,0) AS MATCH_INDEX FROM DUAL;
MATCH_INDEX
1
Quand il y a un mélange de caractères imprimables et de contrôle, à la fois [[:cntrl:]]
et [^[:cntrl:]]
peuvent correspondre à, mais ils vont correspondre à différents indices.
Merci max092012. Cherchez-vous à obtenir chaque occurrence d'un caractère non imprimable par rangée, ou seulement la première occurrence? – alexgibbs