查詢
CREATE DATABASE
創(chuàng)建 ‘db_name’ 數(shù)據(jù)庫.
CREATE DATABASE [IF NOT EXISTS]
一個數(shù)據(jù)庫是庫中表的一個目錄.如果包含“IF NOT EXISTS” ,此數(shù)據(jù)庫已經(jīng)存在蒜鸡,則查詢將不返回錯誤。
CREATE TABLE
CREATE TABLE 查詢有幾種形式.
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] [db.]name [ON CLUSTER cluster](? name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2], ...) ENGINE = engine
在數(shù)據(jù)庫 ‘db’ 中或者當(dāng)前的數(shù)據(jù)庫中如果 ‘db’沒有被設(shè)置(結(jié)構(gòu)被指定在引擎中)創(chuàng)建一個表名為 ‘name’ 的表,表的結(jié)構(gòu)是一個列描述的列表. If 如果索引通過引擎來支持, 他們將被提示作為表引擎的參數(shù).
列描述是最簡單的名稱類型.例如:RegionID UInt32. 對于默認(rèn)值,表達(dá)式能夠被定義.
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] [db.]name AS [db2.]name2 [ENGINE = engine]
創(chuàng)建一個表與另外一個表有相同的結(jié)構(gòu).你能為表指定不同的引擎.如果引擎沒有被指定,相同的引擎將被用在 ‘db2.name2’ 表上.
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] [db.]name ENGINE = engine AS SELECT ...
創(chuàng)建一個表妇菱,其結(jié)構(gòu)類似SELECT查詢語句的結(jié)果,帶有'engine'引擎,使用Select結(jié)果來填充數(shù)據(jù).
如果 IF NOT EXISTS 被指定歧斟,如果表存在,則查詢不返回任何錯誤偏形。在這種情況下静袖,查詢不做任何事情.
默認(rèn)值
列描述符能夠指定一個表達(dá)式為一個默認(rèn)值,方式之一是: DEFAULT 表達(dá)式, MATERIALIZED 表達(dá)式, ALIAS 表達(dá)式. 例如: URLDomain String DEFAULT domain(URL).
如果一個表達(dá)式的默認(rèn)值沒有被定義, 對于數(shù)值型俊扭,默認(rèn)值將被設(shè)置為0, 對于字符串队橙,默認(rèn)值將被設(shè)置為空字符串;對于數(shù)組將被設(shè)置為空數(shù)組萨惑;日期將被設(shè)置為0000-00-00 或者or 0000-00-00 00:00:00. NULLs 不支持.
如果默認(rèn)表達(dá)式被定義, 列類型是可選的. 如果沒有一個顯式的類型捐康,默認(rèn)的表達(dá)式類型將被使用.例如: EventDate DEFAULT toDate(EventTime) -? ‘Date’ 類型將被用于‘EventDate’ 列.
如果數(shù)據(jù)類型和默認(rèn)表達(dá)式被定義.此表達(dá)式將被轉(zhuǎn)換到特定的類型,使用類型轉(zhuǎn)換函數(shù). 例如: Hits UInt32 DEFAULT 0 與下面是等價(jià)的 Hits UInt32 DEFAULT toUInt32(0).
默認(rèn)表達(dá)式能夠被定義作為任意的表達(dá)式庸蔼,表的常量或列.當(dāng)創(chuàng)建和更改表結(jié)構(gòu)時(shí), 它將檢查表達(dá)式不包含 loops. 對于 INSERT語句, 它將檢查表達(dá)式是可解析的 - 參數(shù)傳遞之后解总,所有的列能夠被計(jì)算.
DEFAULT 表達(dá)式
默認(rèn)值. 如果INSERT 語句沒有指定后續(xù)的列,他們將通過計(jì)算后續(xù)的表達(dá)式來填充.
MATERIALIZED 表達(dá)式
Materialized 表達(dá)式. 此列并不指定在INSERT語句中姐仅,因?yàn)樗麄兘?jīng)常被計(jì)算.對于一個INSERT 語句花枫,沒有列的列表,這些列不被考慮萍嬉。另外乌昔,此列并不被替換,當(dāng)在時(shí)SELECT查詢中壤追,使用asterisk. 這保持了使用SELECT *? INSERT 插入表之后的不變性.
查詢解析器
ClickHouse目前有兩種解析器:一個是SQL解析器(遞歸下降分析器)磕道,一個數(shù)據(jù)格式解析器(快速流解析器),第二個僅用于INSERT語句行冰。因此溺蕉,Insert語句使用了上述兩種解析器伶丐。
INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def')
INSERT INTO t VALUES部分使用SQL解析器,DATA部分使用流解析器疯特。
數(shù)據(jù)可以使用任意格式哗魂,當(dāng)接收到請求后,服務(wù)器將不超過’max_query_size’的部分放在RAM中解析(默認(rèn)為1MB)漓雅,剩余部分則使用流解析器录别。ClickHouse和MySQL一樣,對于比較大的INSERT語句不存在解析和處理問題邻吞。
在INSERT語句中使用使用Values格式時(shí)组题,數(shù)據(jù)看上去和SELECT語句的表達(dá)式解析類似,但區(qū)別很大抱冷。Values的格式限制多很多。 接下來我們要講SQL解析器旺遮,對于解析的更多信息,可以參考格式章節(jié)(https://clickhouse.yandex/reference_en.html#Formats) 耿眉。
空白行
語法結(jié)構(gòu)之間可以有任意數(shù)量的空白字符,包括空格跷敬,縮進(jìn),換行西傀,CR桶癣,form feed。
注釋
可以編寫SQL和C風(fēng)格的注釋: 從頭到行尾牙寞,空格可以省略 C風(fēng)格:從/到/饺鹃,允許多行。
關(guān)鍵字
類似SELECT這種的關(guān)鍵字是大小寫不敏感的间雀,但和標(biāo)準(zhǔn)SQL不同悔详,其他關(guān)鍵字(包括列名,方法名等)都是大小寫敏感的惹挟。關(guān)鍵字使用的單詞不是預(yù)留的茄螃,可以在其他命名中使用,它們僅在合適的上下文中被解析為關(guān)鍵字连锯。
標(biāo)識符
不用引號的標(biāo)識符首字符必須是拉丁字符或下劃線归苍,后面可以是拉丁字符用狱,下劃線或數(shù)字,即滿足如下的正則表達(dá)式:
^[a-zA-Z_][0-9a-zA-Z_]*$
例如這些是合法標(biāo)識符:x,1, X_y__Z123
引號中的標(biāo)識符:和MySQL一樣拼弃,使用id的形式夏伊,中間可以使用任意字符,特殊字符(比如`符號本身)可以使用反斜杠轉(zhuǎn)義吻氧。轉(zhuǎn)義規(guī)則和字符串常量相同溺忧。推薦使用沒有括號的標(biāo)識符。
常量
包括數(shù)字常量盯孙,字符串常量和混合常量
數(shù)字常量
數(shù)字常量的解析方式順序:
—首先使用64位有符號數(shù)鲁森,使用'strtoull'方法
—如果不成功,則使用64位無符號數(shù)镀梭,'strtoll'方法
—如果不成功刀森,則使用浮點(diǎn)數(shù),'strtod'方法
—最后不成功則返回錯誤
響應(yīng)數(shù)據(jù)則使用結(jié)果能夠適應(yīng)的最小類型报账,例如1使用Uint8,而256使用Uint16研底,更多信息則請參考上一篇文章 ClickHouse 數(shù)據(jù)類型介紹 。
字符串常量
字符串常量必須使用單引號透罢。特殊字符可以使用反斜杠轉(zhuǎn)義榜晦。轉(zhuǎn)義字符都帶有特殊的含義:
\b, \f, \r, \n, \t, \0, \a, \v, \xHH
其他情況下,對于任意字符c,\c被轉(zhuǎn)成字符c本身羽圃,也就是\表示\乾胶,'表示'字符。
混合常量
數(shù)組中支持混合常量和元組朽寞,混合常量示例:[1, 2, 3]识窿,元組示例:(1, 'Hello, world!', 2)
事實(shí)上他們不是常量,而是使用了數(shù)組構(gòu)造函數(shù)或元組構(gòu)造函數(shù)的表達(dá)式脑融。更多信息參考操作符Operators
數(shù)組至少包含一個元素喻频,元組至少包含兩個元素。元組是專門用于匹配IN語句中的SELECT請求結(jié)果的甥温。通常情況下不能被存儲到數(shù)據(jù)庫中(Memory表除外)妓布。
函數(shù)
函數(shù)就是一個標(biāo)識符匣沼,后面跟著一串(可能為空)用小括號括起來的參數(shù)。和標(biāo)準(zhǔn)的SQL不同跺讯,即使是空的參數(shù)列表殉农,也必須帶有括號超凳,比如now()。
函數(shù)分為普通函數(shù)和聚合函數(shù)暂雹。某些聚合函數(shù)帶有兩組參數(shù)杭跪,比如quantile(0.9)(x)涧尿。這種聚合函數(shù)被稱為參數(shù)化函數(shù)檬贰,第一組參數(shù)就是參數(shù)化方法中的參數(shù)翁涤。對于沒有帶參數(shù)的聚合方法語法就和普通方法一樣。
運(yùn)算符
運(yùn)算符在解析請求時(shí)會被轉(zhuǎn)換為對應(yīng)的函數(shù)号阿,同時(shí)考慮運(yùn)算符的優(yōu)先級和結(jié)合性倦西,例如 1+2+3+4被轉(zhuǎn)換為 plus(plus(1, multiply(2, 3)), 4)赁严,更多內(nèi)容請參考操作符
數(shù)據(jù)類型和表引擎
在CREATE語句中疼约,數(shù)據(jù)類型和表引擎寫法和標(biāo)識符及函數(shù)一致程剥。也就是說他們可能含有參數(shù)列表,也可能不含舔腾。更多信息參考上一篇文章ClickHouse 數(shù)據(jù)類型介紹稳诚。
別名
在SELECT請求中瀑踢,表達(dá)式可以使用AS語法指定別名。表達(dá)式在AS左邊氨距,別名在AS右邊俏让。和標(biāo)準(zhǔn)SQL不同首昔,別名不僅僅可以在表達(dá)式頂層指定,也可以用在任意的語句中沙廉。例如:
表達(dá)式
表達(dá)式具體為函數(shù)撬陵,標(biāo)識符巨税,常量粉臊,運(yùn)算符等扼仲,包在括號中,放在子查詢內(nèi)驰后。表達(dá)式可以包含別名矗愧。多個表達(dá)式使用逗號分隔。函數(shù)和運(yùn)算符也可以使用表達(dá)式作為參數(shù)犯犁。
SQL語句操作
DDL::Create Database
CREATE DATABASE [IF NOT EXISTS] db_name
創(chuàng)建一個名為db_name的數(shù)據(jù)庫酸役,數(shù)據(jù)庫僅僅是一系列表的目錄簇捍。指定了 IF NOT EXISTS后俏拱,如果數(shù)據(jù)庫已經(jīng)存在锅必,語句不會返回錯誤。
DDL::Create Table
建表請求有多種格式
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] [db.]name
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
) ENGINE = engine
在DB數(shù)據(jù)庫中簡歷一個name的表驹愚,如果沒有指定DB則使用當(dāng)前數(shù)據(jù)庫逢捺。結(jié)構(gòu)是括號中指定的格式癞季,引擎使用指定的引擎。表結(jié)構(gòu)是所有列描述的列表志于。如果引擎支持索引伺绽,可以在引擎的參數(shù)中指定嗜湃。
列描述最簡單的情況是"name type",例如RegionID UInt32购披,也可以用表達(dá)式指定默認(rèn)值,下面會有詳細(xì)說明今瀑。
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] [db.]name AS [db2.]name2 [ENGINE = engine]
這個語句使用另一個表的結(jié)構(gòu)建表橘荠,如果沒有指定引擎哥童,則會使用db2.name2的引擎。
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] [db.]name ENGINE = engine AS SELECT ...
上面的語句使用SELECT的結(jié)果作為結(jié)構(gòu)建表匀泊,同時(shí)把SELECT結(jié)果的數(shù)據(jù)插入表中各聘,引擎可以單獨(dú)指定躲因。
在所有上面的方法中大脉,IF NOT EXISTS可以發(fā)揮作用镰矿。
默認(rèn)值
列可以使用下面的語法指定一個默認(rèn)值:DEFAULT expr, MATERIALIZED expr, ALIAS expr秤标。 例如URLDomain String DEFAULT domain(URL)
如果沒有指定默認(rèn)值安疗,對于數(shù)字會默認(rèn)為0荐类,字符串為空字符串,數(shù)組為空數(shù)組屈嗤,日期為0000-00-00饶号,時(shí)間為0000-00-00 00:00:00季蚂,不支持NULL如果指定了默認(rèn)值,類型可以省略算谈,這種情況下使用默認(rèn)值的類型然眼,例如EventDate DEFAULT toDate(EventTime),EventDate的類型會被設(shè)置為Date屿岂。
如果明確指定了類型爷怀,默認(rèn)值的會被轉(zhuǎn)換為目標(biāo)類型晒骇。 例如Hits UInt32 DEFAULT 0 和 Hits UInt32 DEFAULT toUInt32(0)是完全相同的。默認(rèn)值的表達(dá)式中也可以使用表常量和其他列洪囤。建表和修改表結(jié)構(gòu)時(shí)徒坡,會檢查是否包含循環(huán),INSERT語句中瘤缩,會檢查是否表達(dá)式中的所有列都已經(jīng)傳入了喇完。
"DEFAULT expr"表示普通的默認(rèn)值,如果INSERT語句沒有指定相應(yīng)列剥啤,會自動使用表達(dá)式的值填充
"MATERIALIZED expr"表示“物化列”锦溪,這樣的列不允許在INSERT中指定,因?yàn)樗仨氂?jì)算得來府怯。對于沒有指定列的INSERT語句刻诊,這些列不會被考慮在內(nèi),使用SELECT *時(shí)牺丙,這些列也不會返回则涯,因?yàn)閷ELECT * 的結(jié)果使用不指定列的INSERT語句插入式很常見的行為档礁,會引發(fā)問題递礼。
"ALIAS expr"是指別名,這樣的列根本不會被存儲起來一屋。不能夠使用INSERT插入數(shù)據(jù),也不會包括在SELECT * 的返回值中,如果別名是在請求解析階段展開的骄酗,可以使用在SELECT語句中踏烙。
當(dāng)使用ALTER請求來添加新列時(shí)寒屯,這些列的老數(shù)據(jù)不會被寫入。當(dāng)讀取的老數(shù)據(jù)沒有這些新列的值時(shí),默認(rèn)情況下會在線計(jì)算砸紊。然而如果這些表達(dá)式使用了沒有在SELECT語句中出現(xiàn)的列平挑,這些列會被讀取到,當(dāng)然僅在需要的情況下廊酣。
如果向表中添加了新列凡辱,但是后來又修改了默認(rèn)表達(dá)式续徽,老數(shù)據(jù)的值將會更新床绪。當(dāng)運(yùn)行后臺合并操作時(shí)痹雅,原來沒有值的列會在合并后被寫入。不允許為嵌套的數(shù)據(jù)結(jié)構(gòu)設(shè)置默認(rèn)值。
臨時(shí)表
如果指定了TEMPORARY,將會創(chuàng)建臨時(shí)表沦零,臨時(shí)表的特征:
連接結(jié)束或中斷時(shí)千贯,臨時(shí)表會消失魁袜。
臨時(shí)表只能使用內(nèi)存引擎,其它引擎不支持臨時(shí)表鞠呈。
臨時(shí)表不能指定數(shù)據(jù)庫山林,他們是在數(shù)據(jù)庫外創(chuàng)建的。
如果臨時(shí)表和普通表的名字相同诡右,請求沒有指定DB的名字時(shí)帆吻,臨時(shí)表會被使用。
在分布式處理中,一個請求用到的臨時(shí)表會傳給遠(yuǎn)程的服務(wù)器刹衫。
通常情況下,臨時(shí)表不是手動建立的貌夕,而是使用外部數(shù)據(jù),或使用分布式的IN語句時(shí)來自動創(chuàng)建。