Text functions
Change case, cut, trim, pad, search and join text. A letter of any language (Nepali, Chinese, ...) counts as one character.
- Category: Functions — text
- Keywords: text, string, STRING, ascii, chr, translate, overlay, PLACING, normalize, NFC, NFD, NFKC, NFKD, U&, to_ascii, remove accents, bit_length, to_hex, parse_ident, string_to_table, number format, format a number, VARCHAR, UTF-8, Unicode, Nepali, Devanagari, characters, letters, bytes, upper case, lower case, cut text, clean text, ||, join text, concatenate, lcase, ucase, len, mid, instr, locate, position IN, lengthb, format, sprintf, printf, string format, quote a name, quote a value, quote_ident, quote_literal, quote_nullable, SQL injection
- See also: Regular expressions, WHERE, Conversion functions, Bytes, hex and base64, Full-text search
These functions work on text (STRING). KDB keeps text as UTF-8. UTF-8 is the usual way to store the letters of every language. An English letter takes 1 byte; a Nepali letter like न takes 3 bytes.
- Text functions count characters, not bytes.
length('नेपाल')is5. Onlyoctet_lengthcounts bytes. - A
NULLargument givesNULL. Onlyconcat,concat_ws,formatandquote_nullabletake NULLs. - A number, date or
true/falseis first turned into text:length(12.50)is4, because the text is12.5. upper,lowerandinitcapchange the letters of every script that has capitals: English,Ä,ě, Vietnamese, Greek, Cyrillic, Armenian and more. Nepali (Devanagari) has no capitals, so it stays as it is.- Searching (
replace,strpos,starts_with, ...) cares about upper and lower case. To ignore case, uselower()on both sides, ILIKE or a regular expression with the flag'i'. - To find text with a pattern, use LIKE and ILIKE or the regular expression functions.
Example: Clean labels for the company list (sample data: sample)
SELECT symbol,
lower(symbol) AS url_part,
split_part(name, ' ', 1) AS first_word,
length(name) AS letters,
symbol || ' - ' || left(name, 20) AS label
FROM securities
ORDER BY symbol;
Result:
| symbol (SYMBOL) | url_part (STRING) | first_word (STRING) | letters (LONG) | label (STRING) |
|---|---|---|---|---|
| ACME | acme | Acme | 23 | ACME - Acme Investment Comp |
| CITY | city | City | 17 | CITY - City Bank Limited |
| COAST | coast | Coastal | 20 | COAST - Coastal Bank Limited |
| TELCO | telco | Northwind | 25 | TELCO - Northwind Telecom Li |
| VOLT | volt | Volt | 29 | VOLT - Volt River Hydropowe |
(5 rows)
lower
Syntax:
lower(text)
The text with every capital letter made small: lower('CITY') is city, lower('ÄÖ') is äö, lower('ΣΑΣ') is σασ. Letters without capitals (Nepali) stay as they are.
| Argument | Type | Meaning |
|---|---|---|
text | STRING (a number is turned into text) | the text to change |
- Returns:
STRING. - NULL:
lower(NULL)isNULL. - Notes: each letter becomes one letter, as in PostgreSQL:
lower('İ')isi.
Example
SELECT lower('CITY Bank') AS a, lower('नेपाल') AS nepali, lower('ÄBC') AS german, lower('ПРИВЕТ') AS russian, lower(NULL) AS b;
Result:
| a (STRING) | nepali (STRING) | german (STRING) | russian (STRING) | b (STRING) |
|---|---|---|---|---|
| city bank | नेपाल | äbc | привет | NULL |
(1 row)
Example: Log in with the user name in any case
Setup:
CREATE TABLE app_users (id INT PRIMARY KEY AUTO, username STRING NOT NULL, email STRING);
INSERT INTO app_users (username, email) VALUES ('Ram_Sharma', 'ram@example.com'), ('sita', 'sita@example.com');
SELECT id, username FROM app_users WHERE lower(username) = lower('RAM_sharma');
Result:
| id (INT) | username (STRING) |
|---|---|
| 1 | Ram_Sharma |
(1 row)
upper
Syntax:
upper(text)
The text with every small letter made capital: upper('city') is CITY, upper('ěšč') is ĚŠČ. Letters without capitals (Nepali) stay as they are.
| Argument | Type | Meaning |
|---|---|---|
text | STRING (a number is turned into text) | the text to change |
- Returns:
STRING. - NULL:
upper(NULL)isNULL. - Notes:
upper('ß')staysß, as in PostgreSQL (one letter becomes one letter).
Example
SELECT upper('city नेपाल') AS a, upper('Coast') AS b, upper('crème brûlée') AS french, upper(NULL) AS c;
Result:
| a (STRING) | b (STRING) | french (STRING) | c (STRING) |
|---|---|---|---|
| CITY नेपाल | COAST | CRÈME BRÛLÉE | NULL |
(1 row)
Example: Clean stock symbols typed by users
Setup:
CREATE TABLE watchlist (id INT PRIMARY KEY AUTO, typed STRING);
INSERT INTO watchlist (typed) VALUES (' city '), ('Coast'), ('volt ');
SELECT id, '[' || typed || ']' AS typed, upper(trim(typed)) AS symbol FROM watchlist ORDER BY id;
Result:
| id (INT) | typed (STRING) | symbol (STRING) |
|---|---|---|
| 1 | [ city ] | CITY |
| 2 | [Coast] | COAST |
| 3 | [volt ] | VOLT |
(3 rows)
length, char_length, character_length
Syntax:
length(text)
char_length(text)
character_length(text)
The number of characters in the text. A Nepali letter is one character. The three names are the same function.
| Argument | Type | Meaning |
|---|---|---|
text | STRING, BYTES, or a value turned into text | the value to measure |
- Returns:
LONG. - NULL:
length(NULL)isNULL. - Notes: on a
BYTESvalue it counts bytes (see bytes functions). Some Nepali letters are made of 2 characters:केisकplus the signे, solength('के')is2.
Example
SELECT length('CITY') AS a, length('नेपाल') AS nepali, length('के') AS ke, char_length('') AS empty, character_length('City Bank') AS b, length(12.50) AS number, length(NULL) AS c;
Result:
| a (LONG) | nepali (LONG) | ke (LONG) | empty (LONG) | b (LONG) | number (LONG) | c (STRING) |
|---|---|---|---|---|---|---|
| 4 | 5 | 2 | 0 | 9 | 4 | NULL |
(1 row)
Example: Refuse a forum post that is too short or too long
SELECT body, length(body) AS letters, length(body) BETWEEN 10 AND 500 AS ok
FROM (SELECT 'Good results!' AS body
UNION ALL SELECT 'नाफा राम्रो छ'
UNION ALL SELECT 'ok') AS posts;
Result:
| body (STRING) | letters (LONG) | ok (BOOL) |
|---|---|---|
| Good results! | 13 | true |
| नाफा राम्रो छ | 13 | true |
| ok | 2 | false |
(3 rows)
Example: Company names in English and Nepali
Setup:
CREATE TABLE companies (symbol STRING PRIMARY KEY, name STRING, name_ne STRING);
INSERT INTO companies VALUES ('CITY', 'City Bank Limited', 'सिटी बैंक लिमिटेड'), ('VOLT', 'Volt River Hydropower Limited', 'भोल्ट रिभर जलविद्युत लिमिटेड');
SELECT symbol, length(name) AS name_letters, name_ne, length(name_ne) AS ne_letters FROM companies ORDER BY symbol;
Result:
| symbol (STRING) | name_letters (LONG) | name_ne (STRING) | ne_letters (LONG) |
|---|---|---|---|
| CITY | 17 | सिटी बैंक लिमिटेड | 17 |
| VOLT | 29 | भोल्ट रिभर जलविद्युत लिमिटेड | 28 |
(2 rows)
octet_length
Syntax:
octet_length(text)
The number of bytes the text takes in UTF-8. An English letter is 1 byte; a Nepali letter is 3 bytes.
| Argument | Type | Meaning |
|---|---|---|
text | STRING, BYTES, or a value turned into text | the value to measure |
- Returns:
LONG. - NULL:
octet_length(NULL)isNULL. - Notes: use it when a limit is in bytes (for example a column in another program that takes at most 255 bytes). For letters people see, use
length.
Example
SELECT length('नेपाल') AS letters, octet_length('नेपाल') AS bytes, octet_length('CITY') AS english_bytes, octet_length('') AS empty;
Result:
| letters (LONG) | bytes (LONG) | english_bytes (LONG) | empty (LONG) |
|---|---|---|---|
| 5 | 15 | 4 | 0 |
(1 row)
substr, substring
Syntax:
substr(text, start)
substr(text, start, count)
substring(text, start [, count])
A part of the text: count characters from character number start. The first character is number 1. Without count, you get everything to the end. substring is the same function.
| Argument | Type | Meaning |
|---|---|---|
text | STRING (or BYTES) | the text to cut |
start | whole number | the first character to keep; 1 = first. 0 or less starts before the text, so fewer characters are left |
count | whole number | how many characters; must not be negative |
- Returns:
STRING(BYTESfor aBYTESvalue, counted in bytes). - NULL:
NULLwhen any argument isNULL. - Notes:
startafter the end gives empty text'', not an error. A negativecountis an error.startandcountmust be whole numbers:'2'or2.5is an error. The PostgreSQL formsubstring(text FROM 2 FOR 3)works too, and means the same assubstring(text, 2, 3).
Example
SELECT substr('CITY', 3) AS a, substring('CITY', 2, 3) AS b, substr('नेपाल', 2, 2) AS nepali, substr('CITY', 0, 3) AS from_zero, substr('CITY', 10) AS after_end;
Result:
| a (STRING) | b (STRING) | nepali (STRING) | from_zero (STRING) | after_end (STRING) |
|---|---|---|---|---|
| TY | ITY | ेप | CI |
(1 row)
Example: Nepali fiscal year 2082/83: first and last year
SELECT substr('2082/83', 1, 4) AS first_year, substr('2082/83', 6) AS second_year;
Result:
| first_year (STRING) | second_year (STRING) |
|---|---|
| 2082 | 83 |
(1 row)
Example: A negative count is an error (shows an error)
SELECT substr('CITY', 2, -1);
Result:
Error: line 1, column 8: substr: the length must not be negative, got -1
Example: The PostgreSQL FROM ... FOR form
SELECT substring('CITY' FROM 2 FOR 3) AS from_for, substring('CITY' FROM 2) AS to_the_end;
Result:
| from_for (STRING) | to_the_end (STRING) |
|---|---|
| ITY | ITY |
(1 row)
left
Syntax:
left(text, n)
The first n characters of the text. With a negative n, everything except the last -n characters.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text |
n | whole number | how many characters to keep from the start; negative = how many to drop from the end |
- Returns:
STRING. - NULL:
NULLwhen any argument isNULL. - Notes: it never cuts a Nepali letter in half.
nbigger than the text gives the whole text.
Example
SELECT left('CITY', 3) AS a, left('CITY', -2) AS drop_last_2, left('नेपाल बैंक', 5) AS nepali, left('CITY', 99) AS whole;
Result:
| a (STRING) | drop_last_2 (STRING) | nepali (STRING) | whole (STRING) |
|---|---|---|---|
| CIT | CI | नेपाल | CITY |
(1 row)
Example: Short preview of long company names (sample data: sample)
SELECT symbol,
CASE WHEN length(name) > 25 THEN left(name, 25) || '...' ELSE name END AS preview
FROM securities
ORDER BY symbol;
Result:
| symbol (SYMBOL) | preview (STRING) |
|---|---|
| ACME | Acme Investment Company |
| CITY | City Bank Limited |
| COAST | Coastal Bank Limited |
| TELCO | Northwind Telecom Limited |
| VOLT | Volt River Hydropower Lim... |
(5 rows)
right
Syntax:
right(text, n)
The last n characters of the text. With a negative n, everything except the first -n characters.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text |
n | whole number | how many characters to keep from the end; negative = how many to drop from the start |
- Returns:
STRING. - NULL:
NULLwhen any argument isNULL.
Example
SELECT right('CITY', 3) AS a, right('CITY', -2) AS drop_first_2, right('नेपाल', 2) AS nepali;
Result:
| a (STRING) | drop_first_2 (STRING) | nepali (STRING) |
|---|---|---|
| ITY | TY | ाल |
(1 row)
Example: Show only the last 4 digits of a phone number
SELECT '******' || right('9841234567', 4) AS phone_shown;
Result:
| phone_shown (STRING) |
|---|
| ******4567 |
(1 row)
trim, btrim
Syntax:
trim(text)
trim(text, characters)
btrim(text [, characters])
Removes spaces from both ends of the text. With characters, it removes any of those characters from both ends instead. btrim is the same function.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text to clean |
characters | STRING | the characters to remove, in any order; default: space, tab, carriage return and line break |
- Returns:
STRING. - NULL:
NULLwhen any argument isNULL. - Notes:
charactersis a set of single characters, not a word:trim('xyCITYyx', 'xy')removes everyxandyat the ends. Characters in the middle stay. The standard formstrim(BOTH 'x' FROM text),trim(LEADING 'x' FROM text)andtrim(TRAILING 'x' FROM text)work too;LEADINGis ltrim andTRAILINGis rtrim.
Example
SELECT '[' || trim(' CITY ') || ']' AS a, trim('xxCOASTxx', 'x') AS b, btrim('--a-b--', '-') AS c, trim('xyCITYyx', 'xy') AS d;
Result:
| a (STRING) | b (STRING) | c (STRING) | d (STRING) |
|---|---|---|---|
| [CITY] | COAST | a-b | CITY |
(1 row)
Example: Clean a user name before saving it
Setup:
CREATE TABLE app_users (id INT PRIMARY KEY AUTO, username STRING NOT NULL);
INSERT INTO app_users (username) VALUES (lower(trim(' Hari_KC ')));
SELECT id, '[' || username || ']' AS saved FROM app_users;
Result:
INSERT INTO app_users (username) VALUES (lower(trim(' Hari_KC ')))
1 row(s) inserted
SELECT id, '[' || username || ']' AS saved FROM app_users
| id (INT) | saved (STRING) |
|---|---|
| 1 | [hari_kc] |
(1 row)
Example: The standard BOTH / LEADING / TRAILING forms
SELECT trim(BOTH 'x' FROM 'xxCOASTxx') AS both_ends,
trim(LEADING 'x' FROM 'xxCOASTxx') AS front_only,
trim(TRAILING 'x' FROM 'xxCOASTxx') AS end_only;
Result:
| both_ends (STRING) | front_only (STRING) | end_only (STRING) |
|---|---|---|
| COAST | COASTxx | xxCOAST |
(1 row)
ltrim
Syntax:
ltrim(text [, characters])
Like trim, but only at the start (left side) of the text.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text to clean |
characters | STRING | the characters to remove; default: space, tab, carriage return and line break |
- Returns:
STRING. - NULL:
NULLwhen any argument isNULL.
Example
SELECT '[' || ltrim(' CITY ') || ']' AS a, ltrim('00042', '0') AS no_zeros;
Result:
| a (STRING) | no_zeros (STRING) |
|---|---|
| [CITY ] | 42 |
(1 row)
rtrim
Syntax:
rtrim(text [, characters])
Like trim, but only at the end (right side) of the text.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text to clean |
characters | STRING | the characters to remove; default: space, tab, carriage return and line break |
- Returns:
STRING. - NULL:
NULLwhen any argument isNULL.
Example
SELECT '[' || rtrim(' CITY ') || ']' AS a, rtrim('नेपाल।।', '।') AS nepali_full_stop, rtrim('512.500', '0') AS price;
Result:
| a (STRING) | nepali_full_stop (STRING) | price (STRING) |
|---|---|---|
| [ CITY] | नेपाल | 512.5 |
(1 row)
replace
Syntax:
replace(text, from, to)
Replaces every place where from is found in text with to.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text |
from | STRING | the text to find (upper and lower case must match) |
to | STRING | the new text; '' removes from |
- Returns:
STRING. - NULL:
NULLwhen any argument isNULL. - Notes: an empty
fromchanges nothing. The search does not ignore case:replace('City', 'city', 'x')isCity. For patterns (any digit, any space) use regexp_replace.
Example
SELECT replace('a-b-c', '-', '/') AS a, replace('City Bank', 'Bank', 'Bank Limited') AS b, replace('City', 'city', 'x') AS case_matters, replace('CITY', '', 'x') AS empty_from;
Result:
| a (STRING) | b (STRING) | case_matters (STRING) | empty_from (STRING) |
|---|---|---|---|
| a/b/c | City Bank Limited | City | CITY |
(1 row)
Example: Turn a price with commas into a number
SELECT CAST(replace('1,234,567.50', ',', '') AS DOUBLE) AS amount;
Result:
| amount (DOUBLE) |
|---|
| 1234567.5 |
(1 row)
split_part
Syntax:
split_part(text, separator, n)
Splits the text at every separator and gives part number n. 1 is the first part, -1 is the last part.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text to split |
separator | STRING | the text between the parts (one or more characters) |
n | whole number | the part: 1 first, 2 second, -1 last, -2 second last. 0 is an error |
- Returns:
STRING. A part that does not exist gives empty text''. - NULL:
NULLwhen any argument isNULL. - Notes: an empty
separatorgives the whole text as part 1. PostgreSQL also allows negativen(since version 14); MySQL has nosplit_part.
Example
SELECT split_part('2082/83', '/', 1) AS a, split_part('2082/83', '/', -1) AS last, split_part('a,b', ',', 5) AS missing;
Result:
| a (STRING) | last (STRING) | missing (STRING) |
|---|---|---|
| 2082 | 83 |
(1 row)
Example: The domain of each user's email
Setup:
CREATE TABLE app_users (id INT PRIMARY KEY AUTO, email STRING NOT NULL);
INSERT INTO app_users (email) VALUES ('ram@example.com'), ('sita@mail.com.np'), ('hari@example.com');
SELECT split_part(email, '@', 2) AS domain, count(*) AS users FROM app_users GROUP BY split_part(email, '@', 2) ORDER BY domain;
Result:
| domain (STRING) | users (LONG) |
|---|---|
| example.com | 2 |
| mail.com.np | 1 |
(2 rows)
Example: Part number 0 does not exist (shows an error)
SELECT split_part('2082/83', '/', 0);
Result:
Error: line 1, column 8: split_part: the field number must not be 0 (1 = first, -1 = last)
strpos
Syntax:
strpos(text, part)
Where part first starts in text, as a character number (1 = first). 0 when it is not there.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text to search in |
part | STRING | the text to find (case must match) |
- Returns:
LONG. - NULL:
NULLwhen any argument isNULL. - Notes: the number counts characters, so it works with Nepali text. An empty
partgives1.position(part IN text)does the same with the arguments the other way round.
Example
SELECT strpos('CITY', 'IT') AS a, strpos('नेपाल बैंक', 'बैंक') AS nepali, strpos('CITY', 'x') AS not_found, strpos('City', 'cit') AS case_matters;
Result:
| a (LONG) | nepali (LONG) | not_found (LONG) | case_matters (LONG) |
|---|---|---|---|
| 2 | 7 | 0 | 0 |
(1 row)
Example: The user name before the @ of an email
SELECT email, left(email, strpos(email, '@') - 1) AS name
FROM (SELECT 'ram.sharma@example.com' AS email UNION ALL SELECT 'sita@mail.com.np') AS e;
Result:
| email (STRING) | name (STRING) |
|---|---|
| ram.sharma@example.com | ram.sharma |
| sita@mail.com.np | sita |
(2 rows)
position
Syntax:
position(part IN text)
position(part, text)
Where part first starts in text, as a character number (1 = first). 0 when it is not there. The same as strpos(text, part).
| Argument | Type | Meaning |
|---|---|---|
part | STRING | the text to find (case must match) |
text | STRING | the text to search in |
- Returns:
LONG. - NULL:
NULLwhen any argument isNULL. - Notes:
partcomes first here, but second instrpos.
Example
SELECT position('बैंक' IN 'नेपाल बैंक') AS nepali, position('TY' IN 'CITY') AS a, position('TY', 'CITY') AS b, position('x' IN 'CITY') AS not_found;
Result:
| nepali (LONG) | a (LONG) | b (LONG) | not_found (LONG) |
|---|---|---|---|
| 7 | 3 | 3 | 0 |
(1 row)
starts_with
Syntax:
starts_with(text, prefix)
true when the text begins with prefix.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text |
prefix | STRING | the start to look for (case must match) |
- Returns:
BOOL. - NULL:
NULLwhen any argument isNULL. - Notes: an empty
prefixis alwaystrue.text LIKE 'NA%'gives the same answer, and it can use an index.
Example
SELECT starts_with('CITY', 'CI') AS a, starts_with('city', 'CI') AS case_matters, starts_with('CITY', '') AS empty;
Result:
| a (BOOL) | case_matters (BOOL) | empty (BOOL) |
|---|---|---|
| true | false | true |
(1 row)
Example: Companies whose symbol starts with N (sample data: sample)
SELECT symbol, name FROM securities WHERE starts_with(symbol, 'N') ORDER BY symbol;
Result:
| symbol (SYMBOL) | name (STRING) |
|---|
(0 rows)
ends_with
Syntax:
ends_with(text, suffix)
true when the text ends with suffix.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text |
suffix | STRING | the end to look for (case must match) |
- Returns:
BOOL. - NULL:
NULLwhen any argument isNULL.
Example
SELECT ends_with('CITY', 'TY') AS a, ends_with('CITY', 'ty') AS case_matters;
Result:
| a (BOOL) | case_matters (BOOL) |
|---|---|
| true | false |
(1 row)
Example: Users with an email address in Nepal (.np)
Setup:
CREATE TABLE app_users (id INT PRIMARY KEY AUTO, email STRING NOT NULL);
INSERT INTO app_users (email) VALUES ('ram@example.com'), ('sita@mail.com.np'), ('hari@northwind.example.com');
SELECT id, email FROM app_users WHERE ends_with(lower(email), '.np') ORDER BY id;
Result:
| id (INT) | email (STRING) |
|---|---|
| 2 | sita@mail.com.np |
(1 row)
lpad
Syntax:
lpad(text, length)
lpad(text, length, fill)
Makes the text length characters long by adding fill on the left. When the text is longer, it is cut to length.
| Argument | Type | Meaning |
|---|---|---|
text | STRING (a number is turned into text) | the text |
length | whole number | the length you want, in characters (at most 10 000 000) |
fill | STRING | what to add, repeated as needed; default one space |
- Returns:
STRING. - NULL:
NULLwhen any argument isNULL. - Notes:
lengthof 0 or less gives''. An emptyfillgives the text unchanged. A text that is too long is cut at the end (like PostgreSQL).
Example
SELECT lpad('7', 3, '0') AS a, '[' || lpad('5', 3) || ']' AS spaces, lpad('ab', 7, 'xy') AS b, lpad('CITY', 3) AS cut, lpad('न', 3, 'क') AS nepali;
Result:
| a (STRING) | spaces (STRING) | b (STRING) | cut (STRING) | nepali (STRING) |
|---|---|---|---|---|
| 007 | [ 5] | xyxyxab | CIT | ककन |
(1 row)
Example: Invoice numbers with leading zeros
Setup:
CREATE TABLE invoices (id INT PRIMARY KEY AUTO, amount DECIMAL(2));
INSERT INTO invoices (amount) VALUES (1500.00), (250.50), (99999.99);
SELECT 'INV-2082-' || lpad(id, 5, '0') AS invoice_no, amount FROM invoices ORDER BY id;
Result:
| invoice_no (STRING) | amount (DECIMAL(2)) |
|---|---|
| INV-2082-00001 | 1500.00 |
| INV-2082-00002 | 250.50 |
| INV-2082-00003 | 99999.99 |
(3 rows)
Example: The length has a limit (shows an error)
SELECT lpad('a', 20000000);
Result:
Error: line 1, column 8: lpad: the length is larger than 10000000
rpad
Syntax:
rpad(text, length)
rpad(text, length, fill)
Makes the text length characters long by adding fill on the right. When the text is longer, it is cut to length.
| Argument | Type | Meaning |
|---|---|---|
text | STRING (a number is turned into text) | the text |
length | whole number | the length you want, in characters (at most 10 000 000) |
fill | STRING | what to add, repeated as needed; default one space |
- Returns:
STRING. - NULL:
NULLwhen any argument isNULL. - Notes: the same rules as
lpad.
Example
SELECT rpad('CITY', 8, '.') AS a, rpad('CITY', 3) AS cut, '[' || rpad('COAST', 6) || ']' AS spaces;
Result:
| a (STRING) | cut (STRING) | spaces (STRING) |
|---|---|---|
| CITY.... | CIT | [COAST ] |
(1 row)
Example: A simple fixed-width price list (sample data: sample)
SELECT rpad(symbol, 8, '.') || lpad(close, 8) AS line
FROM ochl_day
WHERE time = '2026-09-09'
ORDER BY symbol;
Result:
| line (STRING) |
|---|
| CITY.... 504.6 |
| COAST... 380.1 |
| VOLT.... 187.3 |
(3 rows)
repeat
Syntax:
repeat(text, n)
The text written n times one after another.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text to repeat |
n | whole number | how many times; 0 or less gives '' |
- Returns:
STRING. - NULL:
NULLwhen any argument isNULL. - Notes: the result can be at most 16 MB; a bigger one is an error.
Example
SELECT repeat('ab', 3) AS a, repeat('नम', 2) AS nepali, repeat('-', 0) AS zero;
Result:
| a (STRING) | nepali (STRING) | zero (STRING) |
|---|---|---|
| ababab | नमनम |
(1 row)
Example: A text bar chart of the CITY close price (sample data: sample)
SELECT time, close, repeat('#', floor((close - 500) / 2)) AS bar
FROM ochl_day
WHERE symbol = 'CITY'
ORDER BY time
LIMIT 6;
Result:
| time (TIMESTAMP) | close (DOUBLE) | bar (STRING) |
|---|---|---|
| 2025-12-28T00:00:00.000Z | 542.2 | ##################### |
| 2025-12-29T00:00:00.000Z | 539.7 | ################### |
| 2025-12-30T00:00:00.000Z | 539.3 | ################### |
| 2025-12-31T00:00:00.000Z | 542.4 | ##################### |
| 2026-08-23T00:00:00.000Z | 507.9 | ### |
| 2026-08-24T00:00:00.000Z | 510.3 | ##### |
(6 rows)
reverse
Syntax:
reverse(text)
The characters of the text in the opposite order: reverse('CITY') is YTIC.
| Argument | Type | Meaning |
|---|---|---|
text | STRING (or BYTES) | the text |
- Returns:
STRING(BYTESfor aBYTESvalue, byte by byte). - NULL:
reverse(NULL)isNULL. - Notes: it works character by character. A Nepali vowel sign is its own character, so it lands on the other side of its letter: the result of Nepali text does not read well.
Example
SELECT reverse('CITY') AS a, reverse('12345') AS b, reverse('नेपाल') AS nepali;
Result:
| a (STRING) | b (STRING) | nepali (STRING) |
|---|---|---|
| YTIC | 54321 | लापेन |
(1 row)
concat
Syntax:
concat(value, value, ...)
Joins the values into one text. NULL values are skipped. Numbers, dates and times are turned into text first.
| Argument | Type | Meaning |
|---|---|---|
value | any type | 1 to 64 values to join |
- Returns:
STRING. NeverNULL: when every value isNULL, the result is''. - NULL:
NULLvalues are skipped. - Notes:
a || balso joins text, but it givesNULLwhen one side isNULL.concat()with no values is an error.
Example
SELECT concat('CITY', '-', 2082) AS a, concat('a', NULL, 'b') AS null_skipped, concat(NULL) AS all_null, concat('Close: ', 512.5) AS b;
Result:
| a (STRING) | null_skipped (STRING) | all_null (STRING) | b (STRING) |
|---|---|---|---|
| CITY-2082 | ab | Close: 512.5 |
(1 row)
Example: Full name when the middle name is missing
Setup:
CREATE TABLE app_users (id INT PRIMARY KEY AUTO, first_name STRING, middle_name STRING, last_name STRING);
INSERT INTO app_users (first_name, middle_name, last_name) VALUES ('Ram', 'Bahadur', 'Thapa'), ('Sita', NULL, 'Sharma');
SELECT id,
concat(first_name, ' ', middle_name, ' ', last_name) AS with_concat,
first_name || ' ' || middle_name || ' ' || last_name AS with_pipes
FROM app_users ORDER BY id;
Result:
| id (INT) | with_concat (STRING) | with_pipes (STRING) |
|---|---|---|
| 1 | Ram Bahadur Thapa | Ram Bahadur Thapa |
| 2 | Sita Sharma | NULL |
(2 rows)
concat_ws
Syntax:
concat_ws(separator, value, value, ...)
Joins the values with separator between them. NULL values are skipped, and they get no separator. "ws" means "with separator".
| Argument | Type | Meaning |
|---|---|---|
separator | STRING | the text put between two values |
value | any type | 0 to 63 values to join |
- Returns:
STRING. - NULL: a
NULLseparator givesNULL.NULLvalues are skipped.
Example
SELECT concat_ws(', ', 'a', NULL, 'b') AS a, concat_ws('/', 2082, 83) AS fiscal_year, concat_ws(NULL, 'a', 'b') AS null_separator;
Result:
| a (STRING) | fiscal_year (STRING) | null_separator (STRING) |
|---|---|---|
| a, b | 2082/83 | NULL |
(1 row)
Example: The full name from the example above, without double spaces
Setup:
CREATE TABLE app_users (id INT PRIMARY KEY AUTO, first_name STRING, middle_name STRING, last_name STRING);
INSERT INTO app_users (first_name, middle_name, last_name) VALUES ('Ram', 'Bahadur', 'Thapa'), ('Sita', NULL, 'Sharma');
SELECT id, concat_ws(' ', first_name, middle_name, last_name) AS full_name FROM app_users ORDER BY id;
Result:
| id (INT) | full_name (STRING) |
|---|---|
| 1 | Ram Bahadur Thapa |
| 2 | Sita Sharma |
(2 rows)
format
Syntax:
format(text, value, value, ...)
Fills the places in text with the values, as PostgreSQL does. Its main use is SQL text for EXECUTE in a procedure.
| Place | Puts in | A NULL value |
|---|---|---|
%s | the value as text | nothing (empty text) |
%I | a table or column name, in double quotes when needed | an error |
%L | a value in single quotes, quotes inside doubled | NULL (no quotes) |
%% | one % | |
%2$s | the 2nd value (any place type); the next place takes the 3rd | |
%10s, %-10s | at least 10 characters, filled with spaces on the left (or right with -) |
- Returns:
STRING. ANULLtext givesNULL. - Notes: text made with
%Iand%Lis safe to run as SQL: a quote inside a value stays part of the value. Too few values, or another letter after%, is an error.
Example
SELECT format('%s has %s rows', 'trades', 120) AS plain,
format('SELECT * FROM %I WHERE symbol = %L', 'Daily Prices', 'it''s') AS safe_sql,
format('[%-6s][%6s][%L]', 'ab', 'cd', NULL) AS widths;
Result:
| plain (STRING) | safe_sql (STRING) | widths (STRING) |
|---|---|---|
| trades has 120 rows | SELECT * FROM "Daily Prices" WHERE symbol = 'it''s' | [ab ][ cd][NULL] |
(1 row)
Example: A NULL cannot be a name (shows an error)
SELECT format('SELECT * FROM %I', NULL);
Result:
Error: line 1, column 8: format: %I of format() got NULL: a NULL cannot be a table or column name
quote_ident
Syntax:
quote_ident(name)
The name as it can be written in SQL: as it is when it is all small letters, digits and _ and not a reserved word, otherwise in double quotes (with " doubled). quote_ident('close') is close; quote_ident('Close') is "Close".
- Returns:
STRING.
quote_literal, quote_nullable
Syntax:
quote_literal(value)
quote_nullable(value)
The value as SQL text in single quotes, with every ' doubled: quote_literal('it''s') is 'it''s'. A number is quoted too.
- Returns:
STRING. - NULL:
quote_literal(NULL)isNULL;quote_nullable(NULL)is the textNULL, so the SQL still works.
Example
SELECT quote_ident('close') AS a, quote_ident('Daily Prices') AS b, quote_literal('O''Brien') AS c,
quote_literal(42) AS d, quote_nullable(NULL) AS e;
Result:
| a (STRING) | b (STRING) | c (STRING) | d (STRING) | e (STRING) |
|---|---|---|---|---|
| close | "Daily Prices" | 'O''Brien' | '42' | NULL |
(1 row)
Example: One CSV line per trading day (sample data: sample)
SELECT concat_ws(',', symbol, open, high, low, close) AS csv_line
FROM ochl_day
WHERE symbol = 'COAST'
ORDER BY time
LIMIT 3;
Result:
| csv_line (STRING) |
|---|
| COAST,420.3,426.6,417.6,424.8 |
| COAST,425.9,428.9,421.2,424.2 |
| COAST,423.6,426.1,420.1,423 |
(3 rows)
|| (join text)
Syntax:
text || text
Joins two values into one text: 'CITY' || '-' || 2082 is CITY-2082. A number or date on one side is turned into text.
| Operand | Type | Meaning |
|---|---|---|
| left, right | any type | the two values to join |
- Returns:
STRING. TwoBYTESvalues giveBYTES. - NULL:
NULLon either side givesNULL. Useconcatorcoalescewhen a value can beNULL. - Notes:
||has the same priority as+and-, and they are done from left to right. So'a' || 1 + 2is('a' || 1) + 2, which is an error. PostgreSQL does+first. Write'a' || (1 + 2). MySQL reads||as OR unless a setting is changed; KDB always joins text.
Example
SELECT 'CITY' || '-' || 2082 AS a, 'Close: ' || 512.5 AS b, 'a' || NULL AS with_null, 'total ' || (1 + 2) AS brackets;
Result:
| a (STRING) | b (STRING) | with_null (STRING) | brackets (STRING) |
|---|---|---|---|
| CITY-2082 | Close: 512.5 | NULL | total 3 |
(1 row)
Example: A link to each news article
Setup:
CREATE TABLE news (id LONG PRIMARY KEY AUTO, title STRING NOT NULL, symbol STRING);
INSERT INTO news (title, symbol) VALUES ('City Bank profit rises 18%', 'CITY'), ('Market index closes at 2,840', NULL);
SELECT id, '/news/' || id || '-' || lower(replace(left(title, 20), ' ', '-')) AS url,
'Stock: ' || symbol AS stock_line,
'Stock: ' || coalesce(symbol, 'market') AS fixed
FROM news ORDER BY id;
Result:
| id (LONG) | url (STRING) | stock_line (STRING) | fixed (STRING) |
|---|---|---|---|
| 1 | /news/1-city-bank-profit-ris | Stock: CITY | Stock: CITY |
| 2 | /news/2-market-index-closes- | NULL | Stock: market |
(2 rows)
Example: Without brackets, + is done after || (shows an error)
SELECT 'total ' || 1 + 2;
Result:
Error: line 1, column 22: 'total 1' and '2' are not both numbers
initcap
Syntax:
initcap(text)
Every word gets a capital first letter and small letters after it: initcap('city bank limited') is City Bank Limited.
| Argument | Type | Meaning |
|---|---|---|
text | STRING (a number is turned into text) | the text to change |
- Returns:
STRING. - NULL:
initcap(NULL)isNULL. - Notes: a word ends at anything that is not a letter or a digit, so
ram-bahadurbecomesRam-Bahadur. Letters of every script with capitals change (élanbecomesÉlan); Nepali letters stay as they are. Short words like "and" are capitalised too, so a company name that is already written correctly (Coastal Bank) is better left alone.
Example: Tidy up a name a user typed
SELECT initcap('city bank limited') AS company,
initcap('RAM BAHADUR SHRESTHA') AS person,
initcap('ram-bahadur kc') AS with_hyphen,
initcap(NULL) AS nothing;
Result:
| company (STRING) | person (STRING) | with_hyphen (STRING) | nothing (STRING) |
|---|---|---|---|
| City Bank Limited | Ram Bahadur Shrestha | Ram-Bahadur Kc | NULL |
(1 row)
Example: Company names in title case (sample data: sample)
SELECT symbol, name, initcap(lower(name)) AS title_case
FROM securities
ORDER BY symbol;
Result:
| symbol (SYMBOL) | name (STRING) | title_case (STRING) |
|---|---|---|
| ACME | Acme Investment Company | Acme Investment Company |
| CITY | City Bank Limited | City Bank Limited |
| COAST | Coastal Bank Limited | Coastal Bank Limited |
| TELCO | Northwind Telecom Limited | Northwind Telecom Limited |
| VOLT | Volt River Hydropower Limited | Volt River Hydropower Limited |
(5 rows)
md5
Syntax:
md5(text)
The MD5 hash of the text: 32 lower-case hex digits. The same text always gives the same digits.
| Argument | Type | Meaning |
|---|---|---|
text | STRING (a number or time is turned into text) | the text to hash |
- Returns:
STRING, always 32 characters. - NULL:
md5(NULL)isNULL.md5('')isd41d8cd98f00b204e9800998ecf8427e. - Notes: never use MD5 for passwords. It is broken for that: use password_hash. MD5 is fine as a short fingerprint of a row, to see whether a file or a record changed. It is here because PostgreSQL apps call it. For a strong fingerprint use sha256.
Example: A short fingerprint for each daily candle (sample data: sample)
SELECT symbol, close, md5(symbol || ':' || CAST(time AS STRING)) AS row_key
FROM ochl_day
WHERE time IN '2026-09-10'
ORDER BY symbol;
Result:
| symbol (SYMBOL) | close (DOUBLE) | row_key (STRING) |
|---|---|---|
| CITY | 504.9 | 8c227f18b2f287859fb2008492cc191a |
| COAST | 376.1 | 7e95ad0adf2f1015de2a7078a3a221c6 |
| VOLT | 191.2 | 66b1f4d8c7af12a0fd60ade3702adfb1 |
(3 rows)
Example: The same text always gives the same digits
SELECT md5('CITY') AS a, md5('CITY') = md5('CITY') AS always_same, md5('') AS empty_text, md5(NULL) AS nothing;
Result:
| a (STRING) | always_same (BOOL) | empty_text (STRING) | nothing (STRING) |
|---|---|---|---|
| 859214628431995197c0558f7b5f8ffc | true | d41d8cd98f00b204e9800998ecf8427e | NULL |
(1 row)
to_str
Syntax:
to_str(time, format)
Writes a time as text in the QuestDB format letters. QuestDB apps use this name; KDB's own name for the same job is to_char.
| Argument | Type | Meaning |
|---|---|---|
time | TIMESTAMP, DATE, time text or milliseconds | the time to write |
format | STRING | the pattern, see the table below |
| Letters | Gives | Example |
|---|---|---|
yyyy, yy | year, 4 or 2 digits | 2026, 26 |
MM, MMM | month number, month name | 09, Sep |
dd | day of the month | 10 |
HH, hh | hour 0-23, hour 1-12 | 05, 11 |
mm, ss, SSS | minute, second, millisecond | 15, 00, 123 |
EEE | weekday name | Thu |
a | AM or PM | AM |
'text' | text in single quotes is written as it is | 'at' |
- Returns:
STRING. - NULL:
NULLwhen the time or the format isNULL. - Notes: everything is UTC. For a local clock add its offset first, for example 20700000 for Nepal:
to_str(time + 20700000, 'HH:mm'). Letters KDB does not know are written as they are.UUU(microseconds) is always000, because KDB keeps milliseconds.
Example: Minute candles with a readable clock (sample data: sample)
SELECT to_str(time, 'yyyy-MM-dd') AS day,
to_str(time, 'HH:mm') AS utc_clock,
to_str(time + 20700000, 'HH:mm') AS nepal_clock,
close
FROM ochl_minutes
WHERE symbol = 'CITY'
ORDER BY time
LIMIT 3;
Result:
| day (STRING) | utc_clock (STRING) | nepal_clock (STRING) | close (DOUBLE) |
|---|---|---|---|
| 2026-09-09 | 05:15 | 11:00 | 512.1 |
| 2026-09-09 | 05:16 | 11:01 | 511.9 |
| 2026-09-09 | 05:17 | 11:02 | 511.9 |
(3 rows)
Example: A long date for a report heading (sample data: sample)
SELECT to_str(time, 'EEE dd MMM yyyy') AS trading_day, symbol, close
FROM ochl_day
WHERE time IN '2026-09-10'
ORDER BY symbol;
Result:
| trading_day (STRING) | symbol (SYMBOL) | close (DOUBLE) |
|---|---|---|
| Thu 10 Sep 2026 | CITY | 504.9 |
| Thu 10 Sep 2026 | COAST | 376.1 |
| Thu 10 Sep 2026 | VOLT | 191.2 |
(3 rows)
string_to_array
Syntax:
string_to_array(text, separator)
string_to_array(text, separator, null_text)
Cuts the text into a list at every separator. The PostgreSQL way to turn 'CITY,COAST' into a list of symbols.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text to cut |
separator | STRING | the text between the parts; NULL cuts into single characters |
null_text | STRING | a part equal to this becomes NULL |
- Returns: an array (a
JSONlist). See arrays. - NULL:
string_to_array(NULL, ',')isNULL. Empty text gives an empty list[]. - Notes: an empty separator gives a list with the whole text in it. To go the other way use array_to_string; to make rows out of the list use unnest. To take one part only, split_part is simpler.
Example: A watchlist typed as one line
SELECT string_to_array('CITY,COAST,VOLT', ',') AS symbols,
cardinality(string_to_array('CITY,COAST,VOLT', ',')) AS how_many,
string_to_array('CITY,,VOLT', ',', '') AS empty_part_is_null,
string_to_array('MARKET', NULL) AS every_character;
Result:
| symbols (TEXT[]) | how_many (LONG) | empty_part_is_null (TEXT[]) | every_character (TEXT[]) |
|---|---|---|---|
| ["CITY","COAST","VOLT"] | 3 | ["CITY",null,"VOLT"] | ["M","A","R","K","E","T"] |
(1 row)
Example: Show the companies of a typed watchlist (sample data: sample)
SELECT symbol, name, sector
FROM securities
WHERE symbol IN (SELECT unnest(string_to_array('CITY,VOLT', ',')))
ORDER BY symbol;
Result:
| symbol (SYMBOL) | name (STRING) | sector (STRING) |
|---|---|---|
| CITY | City Bank Limited | Banking |
| VOLT | Volt River Hydropower Limited | Energy |
(2 rows)
string_to_table
Syntax:
string_to_table(text, separator)
string_to_table(text, separator, null_text)
The same cut as string_to_array, but one row per part instead of one list. Use it in FROM or in the SELECT list.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text to cut |
separator | STRING | the text between the parts; NULL cuts into single characters |
null_text | STRING | a part equal to this becomes NULL |
- Returns: rows of
STRING, one per part. InFROMthe column is named after the function, or after the alias:AS t(sym). - NULL:
NULLtext gives no rows. Empty text gives no rows. - Notes: in
FROMthe arguments must be constants. For a column writeSELECT id, string_to_table(col, ',') FROM t.
Example: A typed watchlist as rows
SELECT sym FROM string_to_table('CITY,COAST,VOLT', ',') AS t(sym);
Result:
| sym (STRING) |
|---|
| CITY |
| COAST |
| VOLT |
(3 rows)
ascii
Syntax:
ascii(text)
The number of the first character of the text (its Unicode code point). ascii('A') is 65, ascii('न') is 2344.
- Returns:
LONG. Empty text gives0. - NULL:
ascii(NULL)isNULL.
Example
SELECT ascii('A') AS a, ascii('é') AS e_accent, ascii('नेपाल') AS na, ascii('') AS empty;
Result:
| a (LONG) | e_accent (LONG) | na (LONG) | empty (LONG) |
|---|---|---|---|
| 65 | 233 | 2344 | 0 |
(1 row)
chr
Syntax:
chr(number)
The character with this Unicode number: chr(65) is A, chr(2344) is न. The opposite of ascii.
- Returns:
STRINGof one character. - Errors (as PostgreSQL, SQLSTATE 54000):
0("null character not permitted"), a negative number, a number above 1114111, and the numbers 55296-57343 (they are not characters on their own).
Example
SELECT chr(65) AS a, chr(2344) AS na, chr(10) = E'\n' AS newline;
Result:
| a (STRING) | na (STRING) | newline (BOOL) |
|---|---|---|
| A | न | true |
(1 row)
Example: 0 is not a character (shows an error)
SELECT chr(0);
Result:
Error: line 1, column 8: chr: null character not permitted
translate
Syntax:
translate(text, from, to)
Swaps single characters: each character of from becomes the character at the same place in to. A character of from with no partner in to is removed.
| Argument | Type | Meaning |
|---|---|---|
text | STRING | the text to change |
from | STRING | the characters to find |
to | STRING | what they become, place by place |
- Returns:
STRING. - Notes:
translate('12345', '143', 'ax')isa2x5: 1 becomes a, 4 becomes x, 3 is removed. A character named twice infromuses its first partner. It works on characters of any language. Whenfromandtoare written in the query, the swap table is made once for the whole query.
Example
SELECT translate('12345', '143', 'ax') AS pg_example,
translate('résumé', 'é', 'e') AS no_accents,
translate('98-41-234567', '-', '') AS digits_only;
Result:
| pg_example (STRING) | no_accents (STRING) | digits_only (STRING) |
|---|---|---|
| a2x5 | resume | 9841234567 |
(1 row)
overlay
Syntax:
overlay(text PLACING new_text FROM start)
overlay(text PLACING new_text FROM start FOR count)
overlay(text, new_text, start [, count])
Puts new_text into text at character start, in place of count characters. Without FOR, as many characters as new_text has are replaced.
- Returns:
STRING(BYTESwhentextisBYTES: then it counts bytes). - Notes:
overlay('Txxxxas' PLACING 'hom' FROM 2 FOR 4)isThomas.FOR 0inserts without removing anything. A start past the end adds at the end. - Errors: a start of
0or less: "negative substring length not allowed" (SQLSTATE 22011), as PostgreSQL.
Example
SELECT overlay('Txxxxas' PLACING 'hom' FROM 2 FOR 4) AS thomas,
overlay('98XXXXXX45' PLACING '******' FROM 3) AS masked,
overlay('abc' PLACING '-' FROM 2 FOR 0) AS inserted;
Result:
| thomas (STRING) | masked (STRING) | inserted (STRING) |
|---|---|---|
| Thomas | 98******45 | a-bc |
(1 row)
normalize
Syntax:
normalize(text)
normalize(text, NFC | NFD | NFKC | NFKD)
Brings text into one Unicode normal form. The same letter can be written two ways: á as one character, or as a followed by an accent mark. They look the same but do not compare equal until both are normalized.
| Form | What it does |
|---|---|
NFC (the default) | joins a letter and its marks into one character where Unicode has one |
NFD | takes such characters apart: letter, then marks |
NFKC | like NFC, and turns look-alike characters into plain ones: fi → fi, ² → 2, ① → 1 |
NFKD | like NFD with the same look-alike rule |
- Returns:
STRING. - Notes: the form is written as a bare word, as in PostgreSQL;
'NFC'in quotes works too. Text of plain English letters comes back at once, unchanged. - Errors: another form name: "invalid normalization form" (SQLSTATE 22023).
Example
SELECT normalize(U&'\0061\0301', NFC) = U&'\00E1' AS same_letter,
length(normalize('á', NFD)) AS letters_nfd,
normalize('file ²', NFKC) AS plain;
Result:
| same_letter (BOOL) | letters_nfd (LONG) | plain (STRING) |
|---|---|---|
| true | 2 | file 2 |
(1 row)
U&'...' is PostgreSQL's way to write characters by number: \XXXX (4 hex digits) or \+XXXXXX (6), and \\ for a backslash.
to_ascii
Syntax:
to_ascii(text)
to_ascii(text, 'LATIN1')
The text with accents taken off, in plain ASCII: to_ascii('Karél') is Karel.
- Returns:
STRING. - Notes: Latin-1 letters follow PostgreSQL's table (
Æ→A,ß→B,ÿ→y). Other letters with accents keep their letter (ě→e). A PostgreSQL database in UTF-8 refusesto_asciialtogether; KDB answers as a PostgreSQL database in LATIN1 does. - Errors: a character with no ASCII form, such as Nepali letters: "has no ASCII equivalent" (SQLSTATE 22P05). Encodings other than LATIN1 are not supported (0A000).
Example
SELECT to_ascii('Karél') AS a, to_ascii('Škoda Ørsted') AS b;
Result:
| a (STRING) | b (STRING) |
|---|---|
| Karel | Skoda Orsted |
(1 row)
bit_length
Syntax:
bit_length(text)
The size of the text in bits: 8 times octet_length. bit_length('jose') is 32; bit_length('न') is 24.
- Returns:
LONG. Works onBYTEStoo.
Example
SELECT bit_length('jose') AS english, bit_length('न') AS nepali_letter;
Result:
| english (LONG) | nepali_letter (LONG) |
|---|---|
| 32 | 24 |
(1 row)
to_hex
Syntax:
to_hex(number)
A whole number in hexadecimal (base 16), small letters: to_hex(255) is ff.
- Returns:
STRING. - Notes: a negative number is written as PostgreSQL does: in 32 bits when it fits an
INT(to_hex(-1)isffffffff), else in 64 bits.
Example
SELECT to_hex(255) AS ff, to_hex(4096) AS big, to_hex(-1) AS minus_one;
Result:
| ff (STRING) | big (STRING) | minus_one (STRING) |
|---|---|---|
| ff | 1000 | ffffffff |
(1 row)
parse_ident
Syntax:
parse_ident(name)
parse_ident(name, strict)
Splits a qualified name like "SomeSchema".someTable into its parts, the PostgreSQL way: quotes are taken off, a name without quotes is made lower case, "" inside quotes is one quote.
- Returns: an array of
STRING(aJSONlist). - Notes: with
strict=false, text after the name is ignored:parse_ident('a b', false)is{a}. - Errors: text that is not a valid name ("string is not a valid identifier", SQLSTATE 22023).
Example
SELECT parse_ident('"SomeSchema".someTable') AS parts,
parse_ident('market.Trades')[2] AS table_part;
Result:
| parts (TEXT[]) | table_part (STRING) |
|---|---|
| ["SomeSchema","sometable"] | trades |
(1 row)
to_char for numbers
Syntax:
to_char(number, format)
Writes a number as text with a picture of the digits, exactly as PostgreSQL does. (For times see to_char.)
| Code | Meaning |
|---|---|
9 | a digit; a blank when the number has no digit here |
0 | a digit, 0 when the number has none (leading zeros) |
. or D | the decimal point |
, or G | the thousands separator (left out before the first digit) |
FM | no padding blanks and no trailing zeros |
S, MI, PL, SG | the sign next to the number; - at that place; + at that place; + or - at that place |
PR | a negative number in angle brackets: <485> |
L | the money sign $ |
RN / rn | Roman numerals (1 to 3999) |
TH / th | the ordinal ending: 1st, 22nd, 13th |
V | multiplies by 10 for each 9 after it |
EEEE | scientific notation: 4.86e-04 |
"text" | text as it is |
- Returns:
STRING. WithoutFMthe text starts with a place for the sign:to_char(485, '999')is485. - Notes: a number with more digits than the picture has places shows
#in every place. ADECIMAL(and a number written in the query, such as1234.5) is exact and rounds halves away from zero; aDOUBLErounds as PostgreSQL's float8 does (at most 15 digits). A whole number with a time format ('YYYY-MM-DD') is still read as milliseconds since 1970, as before. A format written in the query is read once for all rows. - Errors: PostgreSQL's (SQLSTATE 42601): "multiple decimal points", "cannot use "S" twice", ...
Example
SELECT to_char(1234.5, 'FM999,999.00') AS money,
to_char(-485, '999PR') AS bracket,
to_char(7, 'FM000') AS padded,
to_char(0.0004859, '9.99EEEE') AS sci,
to_char(2026, 'FMRN') AS roman,
to_char(22, 'FM99th') AS ordinal;
Result:
| money (STRING) | bracket (STRING) | padded (STRING) | sci (STRING) | roman (STRING) | ordinal (STRING) |
|---|---|---|---|---|---|
| 1,234.50 | <485> | 007 | 4.86e-04 | MMXXVI | 22nd |
(1 row)
Example: Turnover in a report (sample data: sample)
SELECT symbol, to_char(sum(close * volume), 'FM999,999,999,990.00') AS turnover
FROM ochl_day
GROUP BY symbol
ORDER BY symbol
LIMIT 3;
Result:
| symbol (SYMBOL) | turnover (STRING) |
|---|---|
| CITY | 1,012,051,301.00 |
| COAST | 640,748,179.00 |
| VOLT | 326,540,767.00 |
(3 rows)