diff --git a/docs/doc/14-sql-commands/00-ddl/20-table/10-ddl-create-table.md b/docs/doc/14-sql-commands/00-ddl/20-table/10-ddl-create-table.md index 3bcb2f9889c45..6b9f9fc83fe21 100644 --- a/docs/doc/14-sql-commands/00-ddl/20-table/10-ddl-create-table.md +++ b/docs/doc/14-sql-commands/00-ddl/20-table/10-ddl-create-table.md @@ -23,8 +23,8 @@ Databend aims to be easy to use by design and does NOT require any of those oper ```sql CREATE [TRANSIENT] TABLE [IF NOT EXISTS] [db.]table_name ( - [ NOT NULL | NULL] [ { DEFAULT }], - [ NOT NULL | NULL] [ { DEFAULT }], + [ NOT NULL | NULL] [ { DEFAULT }], + [ NOT NULL | NULL] [ { DEFAULT }], ... ) [CLUSTER BY( [, , ...] )] @@ -217,9 +217,9 @@ DESC t_null; ## Default Values ```sql -DEFAULT +DEFAULT ``` -Specifies a default value inserted in the column if a value is not specified via an INSERT or CREATE TABLE AS SELECT statement. +Specify a default value(constant expression) inserted in the column if a value is not specified via an INSERT or CREATE TABLE AS SELECT statement. For example: ```sql @@ -260,153 +260,143 @@ Databend’s syntax is difference from MySQL mainly in the data type and some sp ### Create Table +Create a table with a default value for a column (in this case, the `genre` column has 'General' as the default value): + ```sql -CREATE TABLE test(a BIGINT UNSIGNED, b VARCHAR , c VARCHAR DEFAULT concat(b, '-b')); +CREATE TABLE books ( + id BIGINT UNSIGNED, + title VARCHAR, + genre VARCHAR DEFAULT 'General' +); ``` +Describe the table to confirm the structure and the default value for the `genre` column: + ```sql -DESC test; -+-------+--------+------+---------------+ -| Field | Type | Null | Default | -+-------+--------+------+---------------+ -| a | UInt64 | NO | 0 | -| b | String | NO | | -| c | String | NO | concat(b, -b) | -+-------+--------+------+---------------+ +DESC books; ++-------+-----------------+------+---------+-------+ +| Field | Type | Null | Default | Extra | ++-------+-----------------+------+---------+-------+ +| id | BIGINT UNSIGNED | NO | 0 | | +| title | VARCHAR | NO | "" | | +| genre | VARCHAR | NO | 'General'| | ++-------+-----------------+------+---------+-------+ ``` +Insert a row without specifying the `genre`: + ```sql -INSERT INTO test(a,b) VALUES(888, 'stars'); +INSERT INTO books(id, title) VALUES(1, 'Invisible Stars'); ``` +Query the table and notice that the default value 'General' has been set for the `genre` column: + ```sql -SELECT * FROM test; -+------+-------+---------+ -| a | b | c | -+------+-------+---------+ -| 888 | stars | stars-b | -+------+-------+---------+ +SELECT * FROM books; ++----+----------------+---------+ +| id | title | genre | ++----+----------------+---------+ +| 1 | Invisible Stars| General | ++----+----------------+---------+ ``` ### Create Table ... Like -The following example indicates that the command does not copy any data from an existing table but only the column definitions: +Create a new table (`books_copy`) with the same structure as an existing table (`books`): ```sql -CREATE TABLE test2 LIKE test; - -DESC test2; -+-------+--------+------+---------------+ -| Field | Type | Null | Default | -+-------+--------+------+---------------+ -| a | UInt64 | NO | 0 | -| b | String | NO | | -| c | String | NO | concat(b, -b) | -+-------+--------+------+---------------+ - -INSERT INTO test2(a,b) VALUES(888, 'stars'); - --- The new table contains inserted data only. Data in the existing table was not copied. -SELECT * FROM test2; -+------+-------+---------+ -| a | b | c | -+------+-------+---------+ -| 888 | stars | stars-b | -+------+-------+---------+ +CREATE TABLE books_copy LIKE books; ``` -The following example indicates that the command does not copy attributes of an existing table: +Check the structure of the new table: ```sql -CREATE TRANSIENT TABLE tb_01(id int, c1 varchar) CLUSTER BY(id); - -SET hide_options_in_show_create_table=0 - -SHOW CREATE TABLE tb_01; - -Table|Create Table | ------+---------------------------------------------------------------------------------------------------------------------------------------+ -tb_01|CREATE TABLE `tb_01` (¶ `id` INT,¶ `c1` VARCHAR¶) ENGINE=FUSE CLUSTER BY (id) TRANSIENT='T' COMPRESSION='lz4' STORAGE_FORMAT='native'| - - -CREATE TABLE tb_02 LIKE tb_01; - --- The attributes CLUSTER BY and TRANSIENT were not copied to the new table. - -SHOW CREATE TABLE tb_02; - -Table|Create Table | ------+---------------------------------------------------------------------------------------------------------+ -tb_02|CREATE TABLE `tb_02` (¶ `id` INT,¶ `c1` VARCHAR¶) ENGINE=FUSE COMPRESSION='lz4' STORAGE_FORMAT='native'| - --- Add CLUSTER BY using ALTER TABLE. - -ALTER TABLE tb_02 CLUSTER BY(id); - -Table|Create Table | ------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -tb_02|CREATE TABLE `tb_02` (¶ `id` INT,¶ `c1` VARCHAR¶) ENGINE=FUSE CLUSTER BY (id) COMPRESSION='lz4' SNAPSHOT_LOCATION='1/21465/_ss/6b4b16900a4c4134b7dab535b1c93546_v2.json' STORAGE_FORMAT='native'| - --- Not all the table attributes can be added using ALTER TABLE. - -ALTER TABLE tb_02 TRANSIENT='T'; +DESC books_copy; ++-------+-----------------+------+---------+-------+ +| Field | Type | Null | Default | Extra | ++-------+-----------------+------+---------+-------+ +| id | BIGINT UNSIGNED | NO | 0 | | +| title | VARCHAR | NO | "" | | +| genre | VARCHAR | NO | 'General'| | ++-------+-----------------+------+---------+-------+ +``` -SQL Error [1105] [HY000]: Code: 1005, displayText = error: - --> SQL:1:83 - | -1 | /* ApplicationName=DBeaver 23.0.1 - SQLEditor */ alter table tb_02 TRANSIENT='T' - | ----- ^^^^^^^^^ expected `RENAME`, `ADD`, `DROP`, `CLUSTER`, `RECLUSTER`, `FLASHBACK`, or 1 more ... - | | - | while parsing `ALTER TABLE [.]` +Insert a row into the new table and notice that the default value for the `genre` column has been copied: -. +```sql +INSERT INTO books_copy(id, title) VALUES(1, 'Invisible Stars'); + +SELECT * FROM books_copy; ++----+----------------+---------+ +| id | title | genre | ++----+----------------+---------+ +| 1 | Invisible Stars| General | ++----+----------------+---------+ ``` ### Create Table ... As +Create a new table (`books_backup`) that includes data from an existing table (`books`): + ```sql -CREATE TABLE test3 AS SELECT * FROM test2; +CREATE TABLE books_backup AS SELECT * FROM books; ``` + +Describe the new table and notice that the default value for the `genre` column has NOT been copied: + ```sql -DESC test3; -+-------+--------+------+---------------+ -| Field | Type | Null | Default | -+-------+--------+------+---------------+ -| a | UInt64 | NO | 0 | -| b | String | NO | | -| c | String | NO | concat(b, -b) | -+-------+--------+------+---------------+ +DESC books_backup; ++-------+-----------------+------+---------+-------+ +| Field | Type | Null | Default | Extra | ++-------+-----------------+------+---------+-------+ +| id | BIGINT UNSIGNED | NO | 0 | | +| title | VARCHAR | NO | "" | | +| genre | VARCHAR | NO | NULL | | ++-------+-----------------+------+---------+-------+ ``` +Query the new table and notice that the data from the original table has been copied: + ```sql -SELECT * FROM test3; -+------+-------+---------+ -| a | b | c | -+------+-------+---------+ -| 888 | stars | stars-b | -+------+-------+---------+ +SELECT * FROM books_backup; ++----+----------------+---------+ +| id | title | genre | ++----+----------------+---------+ +| 1 | Invisible Stars| General | ++----+----------------+---------+ ``` + ### Create Transient Table +Create a transient table (temporary table) that automatically deletes data after a specified period of time: + ```sql -- Create a transient table -CREATE TRANSIENT TABLE mytemp (c bigint); +CREATE TRANSIENT TABLE visits ( + visitor_id BIGINT +); -- Insert values -insert into mytemp values(1); -insert into mytemp values(2); -insert into mytemp values(3); - --- Only one snapshot is stored. This explains why the Time Travel feature does not work for transient tables. -select count(*) from fuse_snapshot('default', 'mytemp'); -+---------+ -| count() | -+---------+ -| 1 | +INSERT INTO visits VALUES(1); +INSERT INTO visits VALUES(2); +INSERT INTO visits VALUES(3); + +-- Check the inserted data +SELECT * FROM visits; ++-----------+ +| visitor_id | ++-----------+ +| 1 | +| 2 | +| 3 | ++-----------+ ``` ### Create Table ... Snapshot_Location +Create a table from a specific snapshot, allowing you to create a new table based on the data at a specific point in time: + +```sql ```sql CREATE TABLE members ( @@ -456,9 +446,17 @@ Amy ### Create Table ... External_Location +Create a table with data stored on an external location, such as Amazon S3: + ```sql -- Create a table named `mytable` and specify the location `s3://testbucket/admin/data/` for the data storage -CREATE TABLE mytable(a int) -'s3://testbucket/admin/data/' -connection=(ACCESS_KEY_ID='' SECRET_ACCESS_KEY='' endpoint_url='https://s3.amazonaws.com'); +CREATE TABLE mytable ( + a INT +) +external_location='s3://testbucket/admin/data/' +connection=( + ACCESS_KEY_ID='' + SECRET_ACCESS_KEY='' + endpoint_url='https://s3.amazonaws.com' +); ``` diff --git a/docs/doc/14-sql-commands/00-ddl/20-table/90-alter-table-column.md b/docs/doc/14-sql-commands/00-ddl/20-table/90-alter-table-column.md index 8dbf633344c8e..b82a4512ea756 100644 --- a/docs/doc/14-sql-commands/00-ddl/20-table/90-alter-table-column.md +++ b/docs/doc/14-sql-commands/00-ddl/20-table/90-alter-table-column.md @@ -16,37 +16,69 @@ ALTER TABLE can also handle table clustering. For more information, refer to the ## Syntax ```sql -ALTER TABLE [IF EXISTS] ADD COLUMN [ NOT NULL | NULL] [ { DEFAULT }] +ALTER TABLE [IF EXISTS] ADD COLUMN [ NOT NULL | NULL] [ { DEFAULT }] ALTER TABLE [IF EXISTS] DROP COLUMN ``` ## Examples +### Add Column + +Add a new column to an existing table: + ```sql -DESC books; - -Field |Type |Null|Default |Extra| ---------+---------+----+------------+-----+ -price |FLOAT |NO |0.00 | | -pub_time|TIMESTAMP|NO |'1900-01-01'| | -author |VARCHAR |NO |"" | | - -ALTER TABLE books ADD COLUMN region varchar; -DESC books; - -Field |Type |Null|Default |Extra| ---------+---------+----+------------+-----+ -price |FLOAT |NO |0.00 | | -pub_time|TIMESTAMP|NO |'1900-01-01'| | -author |VARCHAR |NO |"" | | -region |VARCHAR |NO |"" | | - -ALTER TABLE books DROP COLUMN region; -DESC books; - -Field |Type |Null|Default |Extra| ---------+---------+----+------------+-----+ -price |FLOAT |NO |0.00 | | -pub_time|TIMESTAMP|NO |'1900-01-01'| | -author |VARCHAR |NO |"" | | +-- Create a table +CREATE TABLE students ( + id BIGINT, + name VARCHAR +); + +-- Add a new column 'age' to the 'students' table +ALTER TABLE students ADD COLUMN age INT; +``` + +### Drop Column + +Remove an existing column from a table: + +```sql +-- Create a table with three columns +CREATE TABLE employees ( + id BIGINT, + name VARCHAR, + department VARCHAR +); + +-- Remove the 'department' column from the 'employees' table +ALTER TABLE employees DROP COLUMN department; +``` + +### Add Column with Default Value + +Add a new column to an existing table with a default value: + +```sql +-- Create a table +CREATE TABLE orders ( + id BIGINT, + item VARCHAR +); + +-- Add a new column 'status' with a default value 'Pending' to the 'orders' table +ALTER TABLE orders ADD COLUMN status VARCHAR DEFAULT 'Pending'; +``` + +### Add Column with NOT NULL Constraint + +Add a new column to an existing table with a NOT NULL constraint, which ensures that a value must be assigned to the column: + +```sql +-- Create a table +CREATE TABLE products ( + id BIGINT, + name VARCHAR +); + +-- Add a new column 'price' with a NOT NULL constraint to the 'products' table +ALTER TABLE products ADD COLUMN price INT NOT NULL; ``` \ No newline at end of file diff --git a/src/query/sql/src/planner/binder/ddl/table.rs b/src/query/sql/src/planner/binder/ddl/table.rs index 680fdeaec8c83..25770d913d607 100644 --- a/src/query/sql/src/planner/binder/ddl/table.rs +++ b/src/query/sql/src/planner/binder/ddl/table.rs @@ -890,7 +890,7 @@ impl Binder { if !cast_expr_to_field_type.is_deterministic(&BUILTIN_FUNCTIONS) { return Err(ErrorCode::SemanticError(format!( - "default expression {cast_expr_to_field_type} is a valid constant", + "default expression {cast_expr_to_field_type} is not a valid constant. Please provide a valid constant expression as the default value.", ))); } @@ -903,7 +903,7 @@ impl Binder { Some(default_expr.to_string()) } else { return Err(ErrorCode::SemanticError(format!( - "default expression {cast_expr_to_field_type} is not a valid constant", + "default expression {cast_expr_to_field_type} is not a valid constant expression. Please provide a valid constant expression as the default value.", ))); } } else {