পোস্টগ্র্রেএসকিউএল "অ্যাকসেন্ট সংবেদনশীল" কোলিশেশন সমর্থন করে?


99

মাইক্রোসফ্ট এসকিউএল সার্ভারে একটি "অ্যাকসেন্ট সংবেদনশীল" কোলেশন (একটি ডাটাবেস, টেবিল বা কলামের জন্য) নির্দিষ্ট করা সম্ভব, যার অর্থ এটি কোনও প্রশ্নের মতোই সম্ভব

SELECT * FROM users WHERE name LIKE 'João'

একটি Joaoনাম সহ একটি সারি খুঁজে ।

আমি জানি যে এটা পোস্টগ্রি মধ্যে স্ট্রিং ব্যবহার থেকে কথা স্ট্রিপ সম্ভব unaccent_string contrib ফাংশন, কিন্তু যদি পোস্টগ্রি তাই এই "অ্যাকসেন্ট অবশ" collations সমর্থন আমি ভাবছি করছি SELECTউপরে কাজ করবে।



আপনি কি কেস-সংবেদনশীলতা বা কেস সংবেদনশীল অনুসন্ধান চান?
ইভান ক্যারল

উত্তর:


212

এর জন্য উদ্বেগহীন মডিউলটি ব্যবহার করুন - যা আপনি সংযুক্ত করছেন তার থেকে সম্পূর্ণ আলাদা।

অচেনা একটি পাঠ্য অনুসন্ধান অভিধান যা লেক্সেমিস থেকে অ্যাকসেন্টগুলি (ডায়াক্রিটিক লক্ষণগুলি) সরিয়ে দেয়।

প্রতি ডাটাবেস প্রতি একবার ইনস্টল করুন:

CREATE EXTENSION unaccent;

আপনি যদি ত্রুটি পান তবে:

ERROR: could not open extension control file
"/usr/share/postgresql/<version>/extension/unaccent.control": No such file or directory

আপনার সম্পর্কিত ডেটাবেস সার্ভারে অবদান প্যাকেজটি ইনস্টল করুন যেমন সম্পর্কিত উত্তরটিতে নির্দেশিত:

অন্যান্য জিনিসের মধ্যে এটি আপনার ফাংশনটি প্রদান করে যা unaccent()আপনি আপনার উদাহরণের সাথে ব্যবহার করতে পারেন (যেখানে LIKEমনে হয় প্রয়োজন নেই)।

SELECT *
FROM   users
WHERE  unaccent(name) = unaccent('João');

সূচক

এই জাতীয় ক্যোয়ারির জন্য একটি সূচক ব্যবহার করতে, এক্সপ্রেশনটিতে একটি সূচক তৈরি করুনতবে পোস্টগ্রিস কেবল IMMUTABLEসূচকগুলির জন্য ফাংশন গ্রহণ করে। যদি কোনও ফাংশন একই ইনপুটটির জন্য আলাদা ফলাফল প্রদান করতে পারে তবে সূচকটি নীরবে ভাঙতে পারে।

unaccent()শুধু STABLEনাIMMUTABLE

দুর্ভাগ্যক্রমে, unaccent()শুধুমাত্র STABLE, না IMMUTABLE। মতে pgsql-বাগ এই থ্রেড , এই কারণে তিন কারণে:

  1. এটি অভিধানের আচরণের উপর নির্ভর করে।
  2. এই অভিধানটির সাথে কোনও হার্ড-ওয়্যারযুক্ত সংযোগ নেই।
  3. সুতরাং এটি বর্তমানের উপরও নির্ভর করে search_path, যা সহজেই পরিবর্তন করতে পারে।

ওয়েবে কিছু টিউটোরিয়াল কেবলমাত্র ফাংশনটিতে অস্থিরতা পরিবর্তন করতে নির্দেশ দেয় IMMUTABLE। এই নিষ্ঠুর বল পদ্ধতিটি কিছু শর্তে ভেঙে যেতে পারে।

অন্যরা একটি সাধারণ IMMUTABLEমোড়ক ফাংশন প্রস্তাব দেয় (যেমন আমি অতীতে নিজেকে করেছি)।

ব্যবহৃত ডিকশনারিটি স্পষ্টভাবে ঘোষণা করে এমন দুটি পরামিতি দিয়ে বৈকল্পিক তৈরি করা যায় কিনা তা নিয়ে চলছে বিতর্ক IMMUTABLEএখানে বা এখানে পড়ুন ।

আরেকটি বিকল্প হ'ল গিথুব-এunaccent() সরবরাহ করা মিউজিক্রাইনজ-এর একটি অপ্রয়োজনীয় ফাংশন সহ এই মডিউলটি । এটি নিজেই পরীক্ষা করে দেখিনি। আমি মনে করি আমি আরও ভাল ধারণা নিয়ে এসেছি :

আপাতত সেরা

অন্যান্য সমাধানগুলি আশেপাশে ভাসমান এবং নিরাপদ হওয়ার কারণে এই পদ্ধতিটি আরও কার্যকর । হার্ড-ওয়্যার্ড স্কিমা-যোগ্য ফাংশন এবং অভিধানের সাহায্যে দ্বি-পরামিতি ফর্মটি কার্যকর করে
একটি IMMUTABLEএসকিউএল র‍্যাপার ফাংশন তৈরি করুন ।

যেহেতু একটি অপরিবর্তনীয় ফাংশন বাসা বাঁধার ফলে ফাংশন ইনলাইনিং নিষ্ক্রিয় হবে, এটি সি-ফাংশনের অনুলিপিটির উপর ভিত্তি করে (জাল) IMMUTABLEপাশাপাশি ঘোষণা করা হবে। এর একমাত্র উদ্দেশ্য এসকিউএল ফাংশন র‌্যাপারে ব্যবহার করা। নিজের ব্যবহার করার জন্য নয়।

সি ফাংশনটির ঘোষণায় অভিধানটি হার্ড-ওয়্যার করার কোনও উপায় না থাকায় পরিশীলনের প্রয়োজন। (সি কোড নিজেই হ্যাক করতে হবে)) এসকিউএল র‌্যাপার ফাংশনটি এটি করে এবং ফাংশনটি ইনলাইনিং এবং এক্সপ্রেশন সূচি উভয়কেই অনুমতি দেয় ।

CREATE OR REPLACE FUNCTION public.immutable_unaccent(regdictionary, text)
  RETURNS text LANGUAGE c IMMUTABLE PARALLEL SAFE STRICT AS
'$libdir/unaccent', 'unaccent_dict';

CREATE OR REPLACE FUNCTION public.f_unaccent(text)
  RETURNS text LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS
$func$
SELECT public.immutable_unaccent(regdictionary 'public.unaccent', $1)
$func$;

ড্রপ PARALLEL SAFEPostgres 9.5 বা তার বেশী বয়সের জন্য উভয় কর্ম থেকে।

publicআপনি যেখানে এক্সটেনশন ইনস্টল করেছেন সেই স্কিমা হচ্ছে ( publicএটি ডিফল্ট) is

সুস্পষ্ট প্রকারের ঘোষণাপত্র ( regdictionary) দূষিত ব্যবহারকারীদের দ্বারা ফাংশনটির ওভারলোডড ভেরিয়েন্টের মাধ্যমে অনুমানমূলক আক্রমণগুলির বিরুদ্ধে প্রতিরক্ষা করে।

পূর্বে, আমি উপর ভিত্তি করে একটি মোড়কের ফাংশন সমর্থন STABLEফাংশন unaccent()unaccent মডিউলটির জাহাজে। যে ফাংশন ইনলাইনিং অক্ষম । এই সংস্করণটি আগে এখানে আমি করা সাধারণ মোড়কের কার্যকারিতার চেয়ে দশগুণ দ্রুত কার্যকর করে।
এবং এটি ইতিমধ্যে দ্বিগুণ দ্রুত ছিল প্রথম সংস্করণ যা ফাংশনটিতে যুক্ত SET search_path = public, pg_tempহয়েছিল - যতক্ষণ না আমি আবিষ্কার করেছি যে অভিধানটিও স্কিমা-যোগ্য হতে পারে। এখনও (পোস্টগ্রাগেস 12) ডকুমেন্টেশন থেকে খুব সুস্পষ্ট নয়।

আপনার যদি সি ফাংশন তৈরি করার জন্য প্রয়োজনীয় সুযোগ-সুবিধার অভাব হয় তবে আপনি দ্বিতীয় সেরা বাস্তবায়নে ফিরে আসবেন: মডিউল দ্বারা সরবরাহিত ফাংশনটির IMMUTABLEচারপাশে একটি ফাংশন র‌্যাপার STABLE unaccent():

CREATE OR REPLACE FUNCTION public.f_unaccent(text)
  RETURNS text AS
$func$
SELECT public.unaccent('public.unaccent', $1)  -- schema-qualify function and dictionary
$func$  LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT;

অবশেষে, ক্যারিগুলিকে দ্রুত করতে এক্সপ্রেশন সূচক :

CREATE INDEX users_unaccent_name_idx ON users(public.f_unaccent(name));

মনে রাখুন পুনঃ ইনডেক্স ফাংশন বা অভিধান কোন পরিবর্তন পর এই ফাংশন জড়িত, একটি ইন-জায়গা প্রধান রিলিজ মত আপগ্রেড যে পুনঃ ইনডেক্স হবে না। সাম্প্রতিক প্রধান রিলিজগুলির unaccentমডিউলের জন্য আপডেট ছিল ।

সূচকের সাথে মেলে জিজ্ঞাসাগুলি মানিয়ে নিন (সুতরাং ক্যোয়ারী পরিকল্পনাকারী এটি ব্যবহার করবে):

SELECT * FROM users
WHERE  f_unaccent(name) = f_unaccent('João');

সঠিক অভিব্যক্তিতে আপনার প্রয়োজন নেই। সেখানে আপনি 'Joao'সরাসরি বিনা চাপযুক্ত স্ট্রিং সরবরাহ করতে পারেন ।

দ্রুত ফাংশনটি এক্সপ্রেশন সূচকটি ব্যবহার করে খুব দ্রুত প্রশ্নগুলিতে অনুবাদ করে না । এটি প্রাক-গণিত মানগুলিতে কাজ করে এবং ইতিমধ্যে খুব দ্রুত। তবে সূচকের রক্ষণাবেক্ষণ এবং সূচি সুবিধাটি ব্যবহার করে না এমন প্রশ্নগুলি।

ক্লায়েন্ট প্রোগ্রামের জন্য নিরাপত্তা Postgres 10.3 / 9.6.8 ইত্যাদি জোরদার করা হয়েছে আপনি প্রয়োজন থেকে স্কিমা-যোগ্যতা অর্জন ফাংশন এবং অভিধানের নাম যখন কোন ইনডেক্স ব্যবহার করা যেমন দেখিয়েছিলেন। দেখা:

Ligatures

Postgres সালে 9.5 বা তার বেশী যারা 'OE' বা মত ligatures 'এস এস' আছে ম্যানুয়ালি সম্প্রসারিত করা (আপনি যে প্রয়োজন হলে), যেহেতু unaccent()সবসময় একটি পরিপূরক একক চিঠি:

SELECT unaccent('Œ Æ œ æ ß');

unaccent
----------
E A e a S

আপনি পোস্টগ্রিস 9.6 এ অচেনা এই আপডেটটি পছন্দ করবেন :

প্রসারিত contrib/unaccentএর মান unaccent.rulesইউনিকোড পরিচিত সব ডায়াক্রিটিক হ্যান্ডেল করতে ফাইল, এবং সঠিকভাবে ligatures প্রসারিত (টমাস মুনরো লিওনার্ড বেনেদেত্তি)

বোল্ড জোর আমার। এখন আমরা পেয়েছি:

SELECT unaccent('Œ Æ œ æ ß');

unaccent
----------
OE AE oe ae ss

প্যাটার্ন ম্যাচিং

স্বেচ্ছাসেবী নিদর্শনগুলির জন্য LIKEবা এর ILIKEসাথে pg_trgmপোস্টগ্র্রেএসকিউএল 9.1 বা তার পরে মডিউলটির সাথে এটি একত্রিত করুন । একটি ট্রিগার জিএন (সাধারণত পছন্দসই) বা জিআইএসটি এক্সপ্রেশন সূচক তৈরি করুন। জিনের উদাহরণ:

CREATE INDEX users_unaccent_name_trgm_idx ON users
USING gin (f_unaccent(name) gin_trgm_ops);

এই জাতীয় প্রশ্নের জন্য ব্যবহার করা যেতে পারে:

SELECT * FROM users
WHERE  f_unaccent(name) LIKE ('%' || f_unaccent('João') || '%');

জিন এবং জিআইএসটি সূচকগুলি প্লেইন বিট্রির চেয়ে বজায় রাখা আরও ব্যয়বহুল:

কেবল বাম-অ্যাঙ্কার্ড নিদর্শনগুলির জন্য সহজ সমাধান রয়েছে। প্যাটার্ন ম্যাচিং এবং পারফরম্যান্স সম্পর্কে আরও:

pg_trgm"অনুরূপতা" ( %) এবং "দূরত্ব" ( <->) এর জন্য দরকারী অপারেটরগুলিও সরবরাহ করে ।

ত্রিগ্রাম সূচকগুলিও ~এট আল সহ সাধারণ নিয়মিত অভিব্যক্তি সমর্থন করে । এবং এর সাথে সংবেদনশীল প্যাটার্নের সাথে মিল রয়েছে ILIKE:


আপনার সমাধানে, সূচিগুলি ব্যবহার করা হয়, বা আমাকে একটি সূচক তৈরি করতে হবে unaccent(name)?
ড্যানিয়েল সেরোদিও

4
@ e3matheus: আমার সরবরাহ করা পূর্ববর্তী সমাধানটি পরীক্ষা না করার জন্য নিজেকে দোষী বোধ করা, আমি এখন পর্যন্ত যা ভেসে বেড়াচ্ছে তার চেয়ে আমার উত্তরটি নতুন এবং আরও ভাল (আইএমএইচও) সমাধান দিয়ে আপডেট করেছি।
এরউইন ব্র্যান্ডসেটেটার

4
আপনার উত্তর পোস্টগ্রিস ডকুমেন্টেশনের মতোই দুর্দান্ত: অসাধারণ!
ইলেক্ট্রোটাইপ

4
আমি অবাক হয়েছি যে এখন আইসিইউ কোলেশন দিয়ে অ্যাকসেন্ট-সংবেদনশীল হওয়া সম্ভব কিনা।
a_horse_with_no_name

4
@ এ_হর্স_বিহীন_নাম_নাম: এখনও এটি পরীক্ষার জন্য আমার কাছে সময় নেই, তবে এটি একটি উদ্দেশ্যপ্রাপ্ত ব্যবহারের ক্ষেত্রে।
এরউইন ব্র্যান্ডসেটেটার

6

না, PostgreSQL সেই অর্থে কোলেশনগুলি সমর্থন করে না

পোস্টগ্রেএসকিউএল এর মতো কোলেশনগুলিকে সমর্থন করে না (অ্যাকসেন্ট সংবেদনশীল বা না) কারণ জিনিসগুলি বাইনারি-সমান না হলে কোনও তুলনা সমান হতে পারে না। এটি কারণ অভ্যন্তরীণভাবে এটি হ্যাশ সূচকের মতো জিনিসগুলির জন্য প্রচুর জটিলতা আনবে। এই কারণে তাদের কঠোরতম অর্থে কোলেশনগুলি কেবল অর্ডারে অর্ডারকে প্রভাবিত করে সাম্যকে নয়।

কর্মক্ষেত্রসমূহ

পূর্ণ-পাঠ্য-অনুসন্ধান অভিধান যা লেসেমিকে অবিচ্ছিন্ন করে।

এফটিএস-এর জন্য, আপনি নিজের অভিধানটি ব্যবহার করে সংজ্ঞা দিতে পারেন unaccent,

CREATE EXTENSION unaccent;

CREATE TEXT SEARCH CONFIGURATION mydict ( COPY = simple );
ALTER TEXT SEARCH CONFIGURATION mydict
  ALTER MAPPING FOR hword, hword_part, word
  WITH unaccent, simple;

যা আপনি তারপর একটি কার্যকরী সূচী দিয়ে সূচক করতে পারেন,

-- Just some sample data...
CREATE TABLE myTable ( myCol )
  AS VALUES ('fóó bar baz'),('qux quz');

-- No index required, but feel free to create one
CREATE INDEX ON myTable
  USING GIST (to_tsvector('mydict', myCol));

আপনি এখন খুব সহজভাবে এটি জিজ্ঞাসা করতে পারেন

SELECT *
FROM myTable
WHERE to_tsvector('mydict', myCol) @@ 'foo & bar'

    mycol    
-------------
 fóó bar baz
(1 row)

আরো দেখুন

নিজেই অচেনা।

unaccentমডিউলটি এফটিএস-সংহতকরণ ছাড়া নিজেও ব্যবহার করা যেতে পারে, এজন্য এরউইনের উত্তর পরীক্ষা করে দেখুন


লক্ষ্য করুন উদ্বোধনী এখানে অনুচ্ছেদ আর Postgres 12 যা চালু হিসাবে কঠোরভাবে সত্য nondeterministic collations । তবে তারা এখনও প্যাটার্ন মেলানো অপারেটর দ্বারা সমর্থিত নয়।
ইনক্লিং

2

আমি নিশ্চিত যে পোস্টগ্রিসএসকিউএল কোলেশনের জন্য অন্তর্নিহিত অপারেটিং সিস্টেমের উপর নির্ভর করে। এটি নতুন কোলিশ তৈরি এবং কলাইজেশন কাস্টমাইজ করতে সহায়তা করে । যদিও আপনার পক্ষে এটি কতটা কাজ হতে পারে তা আমি নিশ্চিত নই। (বেশ কিছু হতে পারে।)


4
নতুন কোলেশন সমর্থন বর্তমানে মূলত অপারেটিং সিস্টেমের লোকেলের জন্য মোড়ক এবং উপকরণগুলির মধ্যে সীমাবদ্ধ। এটা খুব বেসিক। ফিল্টার ফাংশন, কাস্টম তুলকগুলি বা সত্যিকারের কাস্টম কোলেশনগুলির জন্য আপনার যা প্রয়োজন তা কোনওর জন্য কোনও সমর্থন নেই।
ক্রেগ রিঞ্জার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.