الانتقال إلى المحتوى الرئيسي
في هذا القسم، سنستعرض صياغة SQL في ClickHouse. يستخدم ClickHouse صياغةً قائمة على SQL، لكنه يوفّر عددًا من الامتدادات والتحسينات.

تحليل الاستعلام

يوجد نوعان من المحلِّلات في ClickHouse:
  • محلِّل SQL كامل (محلِّل تنازلي تكراري).
  • محلِّل تنسيق البيانات (محلِّل تدفّق سريع).
يُستخدم محلِّل SQL الكامل في جميع الحالات باستثناء استعلام INSERT، إذ يستخدم هذا الاستعلام كلا المحلِّلين. لنستعرض الاستعلام أدناه:
INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def')
كما ذُكر سابقًا، يستخدم استعلام INSERT كلا المحلّلين. يُحلَّل الجزء INSERT INTO t VALUES بواسطة المحلّل الكامل، وتُحلَّل البيانات (1, 'Hello, world'), (2, 'abc'), (3, 'def') بواسطة محلّل تنسيق البيانات، أو محلّل التدفق السريع.
يمكنك أيضًا تشغيل المحلّل الكامل للبيانات باستخدام الإعداد input_format_values_interpret_expressions.عندما تكون قيمة الإعداد المذكور أعلاه 1، يحاول ClickHouse أولًا تحليل القيم باستخدام محلّل التدفق السريع. وإذا أخفق ذلك، يحاول ClickHouse استخدام المحلّل الكامل للبيانات، مع التعامل معها كتعبير SQL expression.
يمكن أن تكون البيانات بأي تنسيق. وعند استلام استعلام، لا يحتسب الخادم في RAM أكثر من max_query_size بايت من الطلب (افتراضيًا، 1 MB)، ويُحلَّل الباقي كتدفق. وذلك لتجنّب المشكلات المرتبطة باستعلامات INSERT الكبيرة، وهي الطريقة الموصى بها لإدراج بياناتك في ClickHouse. عند استخدام تنسيق Values في استعلام INSERT، قد يبدو أن البيانات تُحلَّل بالطريقة نفسها كما في التعبيرات ضمن استعلام SELECT، لكن الأمر ليس كذلك. فتنسيق Values أكثر محدوديةً بكثير. يغطي ما تبقّى من هذا القسم المحلّل الكامل.
لمزيد من المعلومات حول محلّلات التنسيقات، راجع قسم التنسيقات.

المسافات

  • يمكن أن يوجد أي عدد من محارف المسافات بين التركيبات النحوية (بما في ذلك في بداية الاستعلام ونهايته).
  • تشمل محارف المسافات: المسافة، وعلامة الجدولة، وتغذية السطر، وCR، وتغذية الصفحة.

التعليقات

يدعم ClickHouse التعليقات بنمط SQL وبنمط C:
  • تبدأ التعليقات بنمط SQL بـ -- أو #! أو # وتستمر حتى نهاية السطر. ويمكن حذف المسافة بعد -- و#!.
  • التعليقات بنمط C:
    • // (أو أكثر من حرفي /) متبوعًا بنص حتى نهاية السطر. ولا يُشترط وجود مسافات بعد /.
    • يمكن أن تمتد من /* إلى */ في التعليقات متعددة الأسطر. ولا تُشترط المسافات هنا أيضًا.
    • يمكن أن تكون التعليقات بنمط C متداخلة.
على سبيل المثال:
/*
 * Compute the number of days between two dates.
 * /* Returns NULL if either argument is NULL */
 */
SELECT
    dateDiff('day', toDate('2024-01-01'), toDate('2024-12-31')) AS days_in_year, -- 365
    dateDiff('day', toDate('2020-01-01'), today()) AS days_since  #! since 2020
    ///////////////////////////////////////////////////////////////////
    # TODO: add hour/minute variants

الكلمات المفتاحية

يمكن أن تكون الكلمات المفتاحية في ClickHouse إما حساسة لحالة الأحرف أو غير حساسة لحالة الأحرف، بحسب السياق. تكون الكلمات المفتاحية غير حساسة لحالة الأحرف عندما تتوافق مع:
  • معيار SQL. على سبيل المثال، SELECT وselect وSeLeCt كلها صيغ صحيحة.
  • طريقة التنفيذ في بعض أنظمة إدارة قواعد البيانات الشائعة (MySQL أو Postgres). على سبيل المثال، DateTime هو نفسه datetime.
يمكنك التحقق مما إذا كان اسم نوع البيانات حساسًا لحالة الأحرف في جدول system.data_type_families.
وعلى خلاف SQL القياسي، فإن جميع الكلمات المفتاحية الأخرى (بما في ذلك أسماء الدوال) حساسة لحالة الأحرف. إضافةً إلى ذلك، الكلمات المفتاحية ليست كلمات محجوزة. ولا تُعامَل على هذا النحو إلا ضمن السياق المقابل. إذا استخدمت المعرّفات بالاسم نفسه للكلمات المفتاحية، فأحطها بعلامات اقتباس مزدوجة أو بعلامات backticks. على سبيل المثال، يكون الاستعلام التالي صالحًا إذا كان الجدول table_name يحتوي على عمود اسمه "FROM":
SELECT "FROM" FROM table_name

المعرّفات

المعرّفات هي: يمكن أن تكون المعرّفات مقتبسة أو غير مقتبسة، مع أن الأخيرة هي المفضّلة. يجب أن تطابق المعرّفات غير المقتبسة التعبير النمطي ^[a-zA-Z_][0-9a-zA-Z_]*$، ولا يجوز أن تطابق الكلمات المفتاحية. راجع الجدول أدناه للاطلاع على أمثلة للمعرّفات الصالحة وغير الصالحة:
المعرّفات الصالحةالمعرّفات غير الصالحة
xyz, _internal, Id_with_underscores_123_1x, tom@gmail.com, äußerst_schön
إذا كنت تريد استخدام معرّفات تطابق الكلمات المفتاحية، أو تريد استخدام رموز أخرى في المعرّفات، فضعها بين علامتي اقتباس مزدوجتين أو بين علامتي التنصيص الخلفيتين، على سبيل المثال: "id"، `id`.
تنطبق قواعد محارف الهروب نفسها في المعرّفات المقتبسة أيضًا على القيم النصية الحرفية. راجع String لمزيد من التفاصيل.
تجنّب استخدام النقاط في أسماء الأعمدةيمكن تفسير أسماء الأعمدة التي تحتوي على نقاط، والأعمدة التي تشترك في بادئة واحدة مفصولة بنقطة، والأعمدة من النوع Array، كلٌّ منها على أنه جزء من بنية Nested مسطّحة عندما تكون القيمة flatten_nested = 1 (وهي القيمة الافتراضية). وقد يؤدي ذلك إلى تحقّق غير متوقّع من أطوال المصفوفات عند عمليات insert وفرض قيود على إعادة التسمية.تجنّب استخدام النقاط في أسماء الأعمدة إن أمكن. استخدم الشرطات السفلية (_) أو فاصلًا آخر بدلًا من النقاط في أسماء الأعمدة، ما لم تكن تحتاج عمدًا إلى دلالات Nested.

القيم الحرفية

في ClickHouse، القيمة الحرفية هي قيمة تُمثَّل مباشرةً في الاستعلام. وبعبارة أخرى، فهي قيمة ثابتة لا تتغير أثناء تنفيذ الاستعلام. يمكن أن تكون القيم الحرفية: سنستعرض كلًّا منها بمزيد من التفصيل في الأقسام أدناه.

String

يجب أن تُحاط القيم الحرفية النصية بعلامات اقتباس مفردة. علامات الاقتباس المزدوجة غير مدعومة. تعمل آلية الهروب بإحدى الطريقتين التاليتين:
  • استخدام علامة اقتباس مفردة سابقة، إذ لا يمكن تهريب محرف علامة الاقتباس المفردة ' (وهذا المحرف فقط) إلا على هيئة ''، أو
  • استخدام الشرطة المائلة العكسية السابقة مع تسلسلات الهروب المدعومة التالية والمُدرجة في الجدول أدناه.
تفقد الشرطة المائلة العكسية معناها الخاص، أي تُفسَّر حرفيًا، إذا جاءت قبل محارف غير تلك المُدرجة أدناه.
التهريب المدعومالوصف
\xHHتحديد محرف من 8 بت متبوع بأي عدد من الأرقام الست عشرية (H).
\Nمحجوز، ولا يفعل شيئًا (مثلًا SELECT 'a\Nb' تُرجع ab)
\aتنبيه
\bرجوع للخلف
\eمحرف الهروب
\fفاصل صفحة
\nتغذية سطر
\rإرجاع العربة
\tعلامة تبويب أفقية
\vعلامة تبويب عمودية
\0محرف NULL
\\الشرطة المائلة العكسية
\' (أو '')علامة اقتباس مفردة
\"علامة اقتباس مزدوجة
`علامة الاقتباس الخلفية
\/الشرطة المائلة الأمامية
\=علامة يساوي
محارف تحكم ASCII (c <= 31).
في القيم الحرفية النصية، يجب تهريب ' و \ على الأقل باستخدام رموز الهروب \' (أو: '') و \\.

القيم الحرفية العددية

تُحلَّل القيم الحرفية العددية على النحو التالي:
  • إذا كانت القيمة الحرفية مسبوقة بعلامة الطرح -، فيُتخطى الرمز وتُطبَّق الإشارة السالبة على النتيجة بعد التحليل.
  • تُحلَّل القيمة الحرفية العددية أولًا كعدد صحيح غير موقَّع بعرض 64 بت، باستخدام الدالة strtoull.
    • إذا كانت القيمة مسبوقة بـ 0b أو 0x/0X، فيُحلَّل العدد كثنائي أو سداسي عشري، على التوالي.
    • إذا كانت القيمة سالبة وكان مقدارها المطلق أكبر من 263، فسيُعاد خطأ.
  • إذا لم ينجح ذلك، تُحلَّل القيمة بعد ذلك كعدد بفاصلة عائمة باستخدام الدالة strtod.
  • بخلاف ذلك، يُعاد خطأ.
تُحوَّل القيم الحرفية إلى أصغر نوع تتسع له القيمة. على سبيل المثال:
  • يُحلَّل 1 على أنه UInt8
  • يُحلَّل 256 على أنه UInt16.
مهميجب تحويل قيم الأعداد الصحيحة الأعرض من 64 بت (UInt128, Int128, UInt256, Int256) إلى نوع أكبر لكي تُحلَّل بشكل صحيح:
-170141183460469231731687303715884105728::Int128
340282366920938463463374607431768211455::UInt128
-57896044618658097711785492504343953926634992332820282019728792003956564819968::Int256
115792089237316195423570985008687907853269984665640564039457584007913129639935::UInt256
يؤدي ذلك إلى تجاوز الخوارزمية المذكورة أعلاه وتحليل العدد الصحيح باستخدام إجراء يدعم دقةً اعتباطية.وبخلاف ذلك، سيُحلَّل القيمة الحرفية كعدد بفاصلة عائمة، وبالتالي سيكون عرضةً لفقدان الدقة بسبب الاقتطاع.
لمزيد من المعلومات، راجع أنواع البيانات. تُتجاهل الشرطات السفلية _ داخل القيم الحرفية العددية، ويمكن استخدامها لتحسين سهولة القراءة. القيم الحرفية العددية التالية مدعومة:
القيمة الحرفية العدديةأمثلة
الأعداد الصحيحة1, 10_000_000, 18446744073709551615, 01
الأعداد العشرية0.1
الترميز الأسي1e100, -1e-100
أعداد الفاصلة العائمة123.456, inf, nan
سداسي عشري0xc0fe
سلسلة سداسية عشرية متوافقة مع معيار SQLx'c0fe'
ثنائي0b1101
سلسلة ثنائية متوافقة مع معيار SQLb'1101'
القيم الحرفية الثمانية غير مدعومة لتجنب الأخطاء غير المقصودة في التفسير.

المركّبات

تُنشأ المصفوفات باستخدام []: [1, 2, 3]. وتُنشأ الـ Tuples باستخدام (): (1, 'Hello, world!', 2). من الناحية التقنية، لا تُعد هذه قيَمًا حرفية، بل هي تعبيرات تستخدم عامل إنشاء المصفوفة وعامل إنشاء الـ Tuple، على الترتيب. يجب أن تتكوّن المصفوفة من عنصر واحد على الأقل، ويجب أن يتكوّن الـ Tuple من عنصرين على الأقل.
توجد حالة منفصلة عند ظهور الـ Tuples في بند IN ضمن استعلام SELECT. يمكن أن تتضمن نتائج الاستعلام Tuples، لكن لا يمكن حفظ الـ Tuples في قاعدة بيانات (باستثناء الجداول التي تستخدم محرك Memory).

NULL

يُستخدم NULL للإشارة إلى أن قيمةً ما مفقودة. ولتخزين NULL في حقل بجدول، يجب أن يكون هذا الحقل من النوع Nullable.
يجب الانتباه إلى ما يلي بشأن NULL:
  • قد يختلف تمثيل NULL بحسب تنسيق البيانات (إدخالًا أو إخراجًا). لمزيد من المعلومات، راجع تنسيقات البيانات.
  • إن معالجة NULL لها بعض التفاصيل الدقيقة. فعلى سبيل المثال، إذا كانت إحدى وسيطات عملية المقارنة على الأقل هي NULL، فستكون نتيجة هذه العملية أيضًا NULL. وينطبق الأمر نفسه على الضرب والجمع وغير ذلك من العمليات. نوصي بقراءة التوثيق الخاص بكل عملية.
  • في الاستعلامات، يمكنك التحقق من NULL باستخدام المعاملين IS NULL وIS NOT NULL، وكذلك الدالتين المرتبطتين isNull وisNotNull.

Heredoc

يُعد heredoc أسلوبًا لتعريف سلسلة نصية (غالبًا ما تكون متعددة الأسطر) مع الحفاظ على التنسيق الأصلي. ويُعرَّف heredoc بأنه قيمة نصية حرفية مخصّصة توضع بين رمزي $. على سبيل المثال:
SELECT $heredoc$SHOW CREATE VIEW my_view$heredoc$;

┌─'SHOW CREATE VIEW my_view'─┐
│ SHOW CREATE VIEW my_view   │
└────────────────────────────┘
  • تُعالَج أي قيمة بين محدِّدَي Heredoc “كما هي”.
  • يمكنك استخدام Heredoc لتضمين مقتطفات من شيفرات SQL أو HTML أو XML وما إلى ذلك.

تعريف معلمات الاستعلام واستخدامها

تتيح لك معلمات الاستعلام كتابة استعلامات عامة تحتوي على عناصر نائبة مجردة بدلًا من المعرّفات الفعلية. وعند تنفيذ استعلام يتضمن معلمات استعلام، تُفسَّر جميع العناصر النائبة وتُستبدل بقيم معلمات الاستعلام الفعلية. يمكن تعريف معلمات الاستعلام بعدة طرق:
  • SET param_<name>=<value> — باستخدام أمر SET داخل استعلام.
  • --param_<name>='<value>' — كوسيطة لـ clickhouse-client في سطر الأوامر.
  • param_<name>=<value> — كمعلمة في سلسلة استعلام URL لواجهة HTTP.
يمكن الإشارة إلى معلمة استعلام داخل استعلام باستخدام {<name>: <datatype>}، حيث إن <name> هو اسم معلمة الاستعلام و<datatype> هو نوع البيانات الذي تُحوَّل إليه.
على سبيل المثال، يعرّف SQL التالي معلمات بأسماء a وb وc وd، ولكل منها نوع بيانات مختلف:
SET param_a = 13;
SET param_b = 'str';
SET param_c = '2022-08-04 18:30:53';
SET param_d = {'10': [11, 12], '13': [14, 15]};

SELECT
   {a: UInt32},
   {b: String},
   {c: DateTime},
   {d: Map(String, Array(UInt8))};

13    str    2022-08-04 18:30:53    {'10':[11,12],'13':[14,15]}
إذا كنت تستخدم clickhouse-client، فتُحدَّد المعلمات بصيغة --param_name=value. على سبيل المثال، تحمل المعلمة التالية الاسم message وتُسترجع كـ String:
clickhouse-client --param_message='hello' --query="SELECT {message: String}"

hello
إذا كانت معلمة الاستعلام تمثّل اسم database أو table أو function أو أي Identifier آخر، فاستخدم Identifier كنوع لها. على سبيل المثال، يعيد الاستعلام التالي rows من table اسمها uk_price_paid:
SET param_mytablename = "uk_price_paid";
SELECT * FROM {mytablename:Identifier};
يمكن تمرير معلمات الاستعلام كمعلمات في سلسلة استعلام URL مع البادئة param_. على سبيل المثال:
curl -s "http://localhost:8123/?param_message=hello" --data-binary "SELECT {message: String}"

hello
تكتشف واجهة الويب المضمّنة (play.html) تلقائيًا العناصر النائبة للمعلمات بصيغة {name:Type} في الاستعلام، وتعرض حقول إدخال معنونة لكل معلمة. تُضمَّن قيم المعلمات في HTTP request، كما تُحفَظ أيضًا في URL الصفحة لأغراض وضع الإشارات المرجعية والمشاركة.
ليست معلمات الاستعلام بدائل نصية عامة يمكن استخدامها في مواضع عشوائية ضمن استعلامات SQL كيفما اتفق. فهي مُصمَّمة أساسًا للعمل داخل عبارات SELECT بدلًا من المعرّفات أو القيم الحرفية.

الدوال

تُكتب استدعاءات الدوال بصيغة مُعرِّف تتبعه قائمة من الوسائط داخل ()، وقد تكون هذه القائمة فارغة. وعلى خلاف SQL القياسي، تكون الأقواس مطلوبة حتى عندما تكون قائمة الوسائط فارغة. على سبيل المثال:
now()
هناك أيضًا ما يلي: قد تتضمن بعض الدوال التجميعية قائمتين من الوسائط بين قوسين. على سبيل المثال:
quantile (0.9)(x) 
تُسمّى هذه الدوال التجميعية دوالًا “بارامترية”، ويُطلَق على الوسيطات في القائمة الأولى اسم “المعلمات”.
بنية الدوال التجميعية من دون معلمات هي نفسها بنية الدوال العادية.

المعاملات

تُحوَّل المعاملات إلى الدوال المقابلة لها أثناء تحليل الاستعلام، مع مراعاة أولويتها وترابطيتها. على سبيل المثال، التعبير
1 + 2 * 3 + 4
يُحوَّل إلى
plus(plus(1, multiply(2, 3)), 4)`

أنواع البيانات ومحركات الجداول في قاعدة البيانات

تُكتب أنواع البيانات ومحركات الجداول في استعلام CREATE بالطريقة نفسها التي تُكتب بها المعرّفات أو الدوال. وبعبارة أخرى، قد تحتوي على قائمة وسائط بين أقواس، وقد لا تحتوي. لمزيد من المعلومات، راجع الأقسام التالية:

التعبيرات

يمكن أن يكون التعبير أيًا مما يلي:
  • دالة
  • مُعرّف
  • قيمة حرفية
  • تطبيق معامل
  • تعبير بين قوسين
  • استعلام فرعي
  • علامة النجمة
ويمكن أن يتضمن أيضًا اسمًا مستعارًا. قائمة التعبيرات هي تعبير واحد أو أكثر تفصل بينها فاصلات. ويمكن للدوال والمعاملات بدورها أن تأخذ تعبيرات كوسيطات. التعبير الثابت هو تعبير تكون نتيجته معروفة أثناء تحليل الاستعلام، أي قبل التنفيذ. على سبيل المثال، التعبيرات المبنية على القيم الحرفية هي تعبيرات ثابتة.

الأسماء المستعارة للتعبيرات

الاسم المستعار هو اسم يعرّفه المستخدم لـ تعبير ضمن استعلام.
expr AS alias
تُشرح أجزاء الصياغة أعلاه فيما يلي.
جزء من الصياغةالوصفمثالملاحظات
ASالكلمة المفتاحية لتعريف الأسماء المستعارة. يمكنك تعريف الاسم المستعار لاسم جدول أو اسم عمود في عبارة SELECT من دون استخدام الكلمة المفتاحية AS.SELECT table_name_alias.column_name FROM table_name table_name_alias.في الدالة CAST، يكون للكلمة المفتاحية AS معنى آخر. راجع وصف الدالة.
exprأي تعبير يدعمه ClickHouse.SELECT column_name * 2 AS double FROM some_table
aliasاسم لـ expr. يجب أن تتوافق الأسماء المستعارة مع صياغة المعرّفات.SELECT "table t".column_name FROM table_name AS "table t".

ملاحظات حول الاستخدام

  • تسري الأسماء المستعارة على مستوى الاستعلام أو الاستعلام الفرعي بالكامل، ويمكنك تعريف اسم مستعار لأي تعبير في أي جزء من الاستعلام. على سبيل المثال:
SELECT (1 AS n) + 2, n`.
  • الأسماء المستعارة لا تكون مرئية داخل الاستعلامات الفرعية ولا فيما بينها. على سبيل المثال، عند تنفيذ الاستعلام التالي، يُرجع ClickHouse الاستثناء Unknown identifier: num:
`SELECT (SELECT sum(b.a) + num FROM b) - a.a AS num FROM a`
  • إذا تم تعريف اسم مستعار لأعمدة النتيجة في عبارة SELECT داخل استعلام فرعي، فستكون هذه الأعمدة مرئية في الاستعلام الخارجي. على سبيل المثال:
SELECT n + m FROM (SELECT 1 AS n, 2 AS m)`.
  • انتبه إلى الأسماء المستعارة التي تطابق أسماء الأعمدة أو الجداول. لننظر إلى المثال التالي:
CREATE TABLE t
(
    a Int,
    b Int
)
ENGINE = TinyLog();

SELECT
    argMax(a, b),
    sum(b) AS b
FROM t;

Received exception from server (version 18.14.17):
Code: 184. DB::Exception: Received from localhost:9000, 127.0.0.1. DB::Exception: Aggregate function sum(b) is found inside another aggregate function in query.
في المثال السابق، عرّفنا الجدول t بالعمود b. ثم عند تحديد البيانات، عرّفنا الاسم المستعار sum(b) AS b. ونظرًا لأن الأسماء المستعارة عامة النطاق، استبدل ClickHouse الرمز b في التعبير argMax(a, b) بالتعبير sum(b). وقد أدى هذا الاستبدال إلى حدوث الاستثناء.
يمكنك تغيير هذا السلوك الافتراضي بتعيين prefer_column_name_to_alias إلى 1.

النجمة

في استعلام SELECT، يمكن أن تحل النجمة محل التعبير. لمزيد من المعلومات، راجع القسم SELECT.
آخر تعديل في ٢٥ يونيو ٢٠٢٦