提交 95620da6 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 40b88b0d
......@@ -14,6 +14,8 @@ Performance
<h1>Performance</h1>
<a href="#performance_comparison">
Performance Comparison</a><br />
<a href="#poleposition_benchmark">
PolePosition Benchmark</a><br />
<a href="#application_profiling">
Application Profiling</a><br />
<a href="#database_performance_tuning">
......@@ -243,7 +245,8 @@ That means the Open/Close time listed is for opening a connection
if the database is already in use.
</p>
<h3>PolePosition Benchmark</h3>
<br /><a name="poleposition_benchmark"></a>
<h2>PolePosition Benchmark</h2>
<p>
The PolePosition is an open source benchmark. The algorithms are all quite simple.
It was developed / sponsored by db4o.
......
......@@ -34,6 +34,8 @@ Tutorial
Java Web Start / JNLP</a><br />
<a href="#fulltext">
Fulltext Search</a><br />
<a href="#user_defined_variables">
User Defined Variables</a><br />
<br /><a name="tutorial_starting_h2_console"></a>
<h2>Starting and Using the H2 Console</h2>
......@@ -592,4 +594,27 @@ You can also call the index from within a Java application:
org.h2.fulltext.FullTextLucene.search(conn, text, limit, offset)
</pre>
<br /><a name="user_defined_variables"></a>
<h2>User Defined Variables</h2>
<p>
This database supports user defined variables. Variables start with @ and can be used whereever
expressions or parameters are used. Variables not persisted and session scoped, that means only visible for
the session where they are defined. A value is usually assigned using the SET command:
</p>
<pre>
SET @USER = 'Joe';
</pre>
<p>
It is also possible to change a value using the SET() method. This is useful in queries:
</p>
<pre>
SET @TOTAL = NULL;
SELECT X, SET(@TOTAL, IFNULL(@TOTAL, 1.) * X) F FROM SYSTEM_RANGE(1, 50);
</pre>
<p>
Variables that are not set evaluate to NULL. The data type of a user defined variable is the data type
of the value assigned to it, that means it is not necessary (or possible) to declare variable names before using them.
There are no restrictions on the assigned values, large objects (LOBs) are supported as well.
</p>
</div></td></tr></table></body></html>
......@@ -139,6 +139,7 @@ public abstract class Command implements CommandInterface {
}
private void stop() throws SQLException {
session.closeTemporaryResults();
session.setCurrentCommand(null, 0);
if (!isTransactional()) {
session.commit(true);
......
......@@ -223,12 +223,19 @@ public abstract class Query extends Prepared {
}
}
lastParameters = params;
closeLastResult();
lastResult = queryWithoutCache(limit);
this.lastEvaluated = now;
lastLimit = limit;
return lastResult;
}
private void closeLastResult() {
if (lastResult != null) {
lastResult.close();
}
}
protected void initOrder(ObjectArray expressions, ObjectArray expressionSQL, ObjectArray orderList, int visible,
boolean mustBeInResult) throws SQLException {
for (int i = 0; i < orderList.size(); i++) {
......
......@@ -229,7 +229,7 @@ public class SysProperties {
/**
* System property <code>h2.optimizeInJoin</code> (default: false).<br />
* Optimize IN(SELECT ...) comparisons by converting them to a join.
* Optimize IN(...) comparisons by converting them to inner joins.
*/
public static final boolean OPTIMIZE_IN_JOIN = getBooleanSetting("h2.optimizeInJoin", false);
......@@ -247,7 +247,7 @@ public class SysProperties {
/**
* System property <code>h2.optimizeNot</code> (default: true).<br />
* Optimize NOT expression.
* Optimize NOT conditions by removing the NOT and inverting the condition.
*/
public static final boolean OPTIMIZE_NOT = getBooleanSetting("h2.optimizeNot", true);
......@@ -301,7 +301,7 @@ public class SysProperties {
/**
* System property <code>h2.traceIO</code> (default: false).<br />
* Trace I/O operations.
* Trace all I/O operations.
*/
public static final boolean TRACE_IO = getBooleanSetting("h2.traceIO", false);
......
......@@ -60,6 +60,7 @@ import org.h2.util.StringUtils;
import org.h2.value.CompareMode;
import org.h2.value.Value;
import org.h2.value.ValueInt;
import org.h2.value.ValueLob;
/**
* There is one database object per open database.
......@@ -870,6 +871,14 @@ public class Database implements DataHandler {
} catch (SQLException e) {
traceSystem.getTrace(Trace.DATABASE).error("close", e);
}
// remove all session variables
if (persistent) {
try {
ValueLob.removeAllForTable(this, ValueLob.TABLE_ID_SESSION);
} catch (SQLException e) {
traceSystem.getTrace(Trace.DATABASE).error("close", e);
}
}
try {
closeOpenFilesAndUnlock();
} catch (SQLException e) {
......
......@@ -26,6 +26,7 @@ import org.h2.log.UndoLogRecord;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.message.TraceSystem;
import org.h2.result.LocalResult;
import org.h2.result.Row;
import org.h2.schema.Schema;
import org.h2.store.DataHandler;
......@@ -33,6 +34,7 @@ import org.h2.table.Table;
import org.h2.util.ObjectArray;
import org.h2.util.ObjectUtils;
import org.h2.value.Value;
import org.h2.value.ValueLob;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
......@@ -77,6 +79,7 @@ public class Session implements SessionInterface {
private long sessionStart = System.currentTimeMillis();
private long currentCommandStart;
private HashMap variables;
private HashSet temporaryResults;
public Session() {
}
......@@ -87,12 +90,22 @@ public class Session implements SessionInterface {
}
}
public void setVariable(String name, Value value) {
public void setVariable(String name, Value value) throws SQLException {
initVariables();
Value old;
if (value == ValueNull.INSTANCE) {
variables.remove(name);
old = (Value) variables.remove(name);
} else {
variables.put(name, value);
if (value instanceof ValueLob) {
// link it, to make sure we have our own file
value = value.link(database, ValueLob.TABLE_ID_SESSION);
}
old = (Value) variables.put(name, value);
}
if (old != null) {
// close the old value (in case it is a lob)
old.unlink();
old.close();
}
}
......@@ -663,4 +676,20 @@ public class Session implements SessionInterface {
}
}
public void addTemporaryResult(LocalResult result) {
if (temporaryResults == null) {
temporaryResults = new HashSet();
}
temporaryResults.add(result);
}
public void closeTemporaryResults() {
if (temporaryResults != null) {
for (Iterator it = temporaryResults.iterator(); it.hasNext();) {
LocalResult result = (LocalResult) it.next();
result.close();
}
}
}
}
......@@ -28,12 +28,9 @@ public class ConditionExists extends Condition {
public Value getValue(Session session) throws SQLException {
query.setSession(session);
LocalResult result = query.query(1);
try {
session.addTemporaryResult(result);
boolean r = result.getRowCount() > 0;
return ValueBoolean.get(r);
} finally {
result.close();
}
}
public Expression optimize(Session session) throws SQLException {
......
......@@ -46,9 +46,9 @@ public class ConditionInSelect extends Condition {
}
query.setSession(session);
LocalResult rows = query.query(0);
session.addTemporaryResult(rows);
boolean hasNull = false;
boolean result = all;
try {
while (rows.next()) {
boolean value;
Value r = rows.currentRow()[0];
......@@ -70,9 +70,6 @@ public class ConditionInSelect extends Condition {
return ValueNull.INSTANCE;
}
return ValueBoolean.get(result);
} finally {
rows.close();
}
}
public void mapColumns(ColumnResolver resolver, int queryLevel) throws SQLException {
......
......@@ -114,8 +114,8 @@ public class Function extends Expression implements FunctionCall {
datePart.put("MONTH", ObjectUtils.getInteger(Calendar.MONTH));
datePart.put("DD", ObjectUtils.getInteger(Calendar.DATE));
datePart.put("DAY", ObjectUtils.getInteger(Calendar.DATE));
datePart.put("HH", ObjectUtils.getInteger(Calendar.HOUR));
datePart.put("HOUR", ObjectUtils.getInteger(Calendar.HOUR));
datePart.put("HH", ObjectUtils.getInteger(Calendar.HOUR_OF_DAY));
datePart.put("HOUR", ObjectUtils.getInteger(Calendar.HOUR_OF_DAY));
datePart.put("MI", ObjectUtils.getInteger(Calendar.MINUTE));
datePart.put("MINUTE", ObjectUtils.getInteger(Calendar.MINUTE));
datePart.put("SS", ObjectUtils.getInteger(Calendar.SECOND));
......@@ -1102,7 +1102,7 @@ public class Function extends Expression implements FunctionCall {
// return (t2 - t1) / 1000;
// case Calendar.MINUTE:
// return (t2 - t1) / 1000 / 60;
// case Calendar.HOUR:
// case Calendar.HOUR_OF_DAY:
// return (t2 - t1) / 1000 / 60 / 60;
// case Calendar.DATE:
// return (t2 - t1) / 1000 / 60 / 60 / 24;
......@@ -1170,7 +1170,7 @@ public class Function extends Expression implements FunctionCall {
return t2 - t1;
case Calendar.SECOND:
case Calendar.MINUTE:
case Calendar.HOUR: {
case Calendar.HOUR_OF_DAY: {
// first 'normalize' the numbers so both are not negative
long hour = 60 * 60 * 1000;
long add = Math.min(t1 / hour * hour, t2 / hour * hour);
......@@ -1181,7 +1181,7 @@ public class Function extends Expression implements FunctionCall {
return t2 / 1000 - t1 / 1000;
case Calendar.MINUTE:
return t2 / (60 * 1000) - t1 / (60 * 1000);
case Calendar.HOUR:
case Calendar.HOUR_OF_DAY:
return t2 / hour - t1 / hour;
default:
throw Message.getInternalError("field:" + field);
......
......@@ -67,11 +67,11 @@ public class FullTextSettings {
private static String getIndexPath(Connection conn) throws SQLException {
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("CALL DATABASE_PATH()");
ResultSet rs = stat.executeQuery("CALL IFNULL(DATABASE_PATH(), 'MEM:' || DATABASE())");
rs.next();
String path = rs.getString(1);
if (path == null) {
throw new SQLException("FULLTEXT", "Fulltext search for in-memory databases is not supported.");
if ("MEM:UNNAMED".equals(path)) {
throw new SQLException("FULLTEXT", "Fulltext search for private (unnamed) in-memory databases is not supported.");
}
rs.close();
return path;
......
......@@ -83,7 +83,7 @@ public class LocalResult implements ResultInterface {
}
public LocalResult createShallowCopy(Session session) {
if (disk == null && rows == null || rows.size() < rowCount) {
if (disk == null && (rows == null || rows.size() < rowCount)) {
return null;
}
LocalResult copy = new LocalResult(0);
......
......@@ -223,19 +223,21 @@ public class PageParser {
return escapeHtml(s, true);
}
public static String escapeHtml(String s, boolean convertBreak) {
private static String escapeHtml(String s, boolean convertBreak) {
if (s == null) {
return null;
}
if (convertBreak) {
if (s.length() == 0) {
return "&nbsp;";
}
}
StringBuffer buff = new StringBuffer(s.length());
boolean convertSpace = true;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == ' ') {
if (convertSpace) {
if (convertSpace && convertBreak) {
buff.append("&nbsp;");
} else {
buff.append(' ');
......
......@@ -463,7 +463,7 @@ public class Column {
}
public String getDefaultSQL() {
return defaultExpression == null ? "" : defaultExpression.getSQL();
return defaultExpression == null ? null : defaultExpression.getSQL();
}
public int getPrecisionAsInt() {
......
......@@ -608,6 +608,11 @@ public class StringUtils {
return buff.append('\"').toString();
}
/**
* Check if a String is null or empty (the length is null).
*
* @return true if it is null or empty
*/
public static boolean isNullOrEmpty(String s) {
return s == null || s.length() == 0;
}
......
......@@ -35,6 +35,8 @@ public class ValueLob extends Value {
// TODO lob: concatenate function for blob and clob (to create a large blob from pieces)
// and a getpart function (to get it in pieces) and make sure a file is created!
public static final int TABLE_ID_SESSION = -1;
private final int type;
private long precision;
private DataHandler handler;
......
......@@ -150,14 +150,59 @@ java org.h2.test.TestAll timer
/*
CACHE_SIZE_INDEX_DEFAULT
INTERNAL
ErrorCodes doesn't look nice
drop table test;
create table test(id int);
insert into test values(1);
select extract(hour from timestamp '2001-02-03 14:15:16') from test;
select extract(hour from '2001-02-03 14:15:16') from test;
select hour('2001-02-03 14:15:16') from test;
A bug was introduced into the H2 Console's Web Server last year. When
opening the Console (default port 8082), the user is presented with
web page that includes a <select> of Saved Settings
(.h2.server.properties). If the Name of a setting contains consecutive
spaces, the spaces may get escaped to '&nbsp;'. That causes the name
in HTML to no longer match the name from the properties file. Thus,
the setting cannot be selected by the user.
Noting a 'compatibility' difference between H2 and Oracle or MySQL. In
org.h2.expression.Fucntion.java, you map 'HOUR' to Calendar.HOUR
instead of Calendar.HOUR_OF_DAY. This, given a timestamp at 6pm,
Oracle and MySQL will return 18 whereas H2 will return 6. It seems a
bug in H2 to me, because trying to GROUP on EXTRACT(HOUR FROM...) will
fold all afternoon aggregates into the morning aggregates. Even if it
is a bug in H2, I guess it could be problematic to 'fix it' since
existing users of H2 might rely the 'buggy' behaviour. Could you
change the default to HOUR_OF_DAY and make it an option to keep the
old HOUR behaviour?
flights.zip example usage
light.zip source code and binary jar
copyright 2008
other databases return SQL 'null' if there is no column default defined. The next release of H2 will do the same.
google analytics to web site
quaere:
where(test(a).bigger(b));
where(test(a, BIGGER, b));
where(test(a).bigger(b).and(a).smaller(b));
Roadmap:
History:
The method EXTRACT(HOUR FROM...) returned the wrong values (0 to 11 instead of 0 to 23).
For compatibility with other databases the column default (COLUMN_DEF) for columns without default is now null (it was an empty string).
Statements that contain very large subqueries (where the subquery result does not fit in memory) are now faster.
Variables: large objects (CLOB and BLOB) that don't fit in memory did not work correctly when used as variables.
Fulltext search is now supported in named in-memory databases.
Test Recovery with MAX_LOG_FILE_SIZE=1; test with various log file sizes
......
......@@ -21,12 +21,36 @@ public class TestBigResult extends TestBase {
if (config.memory) {
return;
}
testLargeSubquery();
testLargeUpdateDelete();
testCloseConnectionDelete();
testOrderGroup();
testLimitBufferedResult();
}
private void testLargeSubquery() throws Exception {
deleteDb("bigResult");
Connection conn = getConnection("bigResult");
Statement stat = conn.createStatement();
int len = getSize(1000, 4000);
stat.execute("SET MAX_MEMORY_ROWS " + (len / 10));
stat.execute("CREATE TABLE RECOVERY(TRANSACTION_ID INT, SQL_STMT VARCHAR)");
stat.execute("INSERT INTO RECOVERY " +
"SELECT X, CASE MOD(X, 2) WHEN 0 THEN 'commit' ELSE 'begin' END " +
"FROM SYSTEM_RANGE(1, "+len+")");
ResultSet rs = stat.executeQuery("SELECT * FROM RECOVERY WHERE SQL_STMT LIKE 'begin%' AND " +
"TRANSACTION_ID NOT IN(SELECT TRANSACTION_ID FROM RECOVERY " +
"WHERE SQL_STMT='commit' OR SQL_STMT='rollback')");
int count = 0, last = 1;
while (rs.next()) {
check(last, rs.getInt(1));
last += 2;
count++;
}
check(len / 2, count);
conn.close();
}
private void testLargeUpdateDelete() throws Exception {
deleteDb("bigResult");
Connection conn = getConnection("bigResult");
......
......@@ -34,6 +34,7 @@ public class TestLob extends TestBase {
if (config.memory) {
return;
}
testLobVariable();
testLobDrop();
testLobNoClose();
testLobTransactions(10);
......@@ -54,6 +55,23 @@ public class TestLob extends TestBase {
testJavaObject();
}
private void testLobVariable() throws Exception {
deleteDb("lob");
Connection conn = reconnect(null);
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(ID INT, DATA CLOB)");
stat.execute("INSERT INTO TEST VALUES(1, SPACE(100000))");
stat.execute("SET @TOTAL = SELECT DATA FROM TEST WHERE ID=1");
stat.execute("DROP TABLE TEST");
stat.execute("CALL @TOTAL LIKE '%X'");
stat.execute("CREATE TABLE TEST(ID INT, DATA CLOB)");
stat.execute("INSERT INTO TEST VALUES(1, @TOTAL)");
stat.execute("INSERT INTO TEST VALUES(2, @TOTAL)");
stat.execute("DROP TABLE TEST");
stat.execute("CALL @TOTAL LIKE '%X'");
conn.close();
}
private void testLobDrop() throws Exception {
if (config.logMode == 0 || config.networked) {
return;
......
......@@ -29,6 +29,7 @@ public class TestMetaData extends TestBase {
deleteDb("metaData");
conn = getConnection("metaData");
testColumnDefault();
testCrossReferences();
testProcedureColumns();
......@@ -190,6 +191,22 @@ public class TestMetaData extends TestBase {
}
private void testColumnDefault() throws Exception {
DatabaseMetaData meta = conn.getMetaData();
ResultSet rs;
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(A INT, B INT DEFAULT NULL)");
rs = meta.getColumns(null, null, "TEST", null);
rs.next();
check("A", rs.getString("COLUMN_NAME"));
check(null, rs.getString("COLUMN_DEF"));
rs.next();
check("B", rs.getString("COLUMN_NAME"));
check("NULL", rs.getString("COLUMN_DEF"));
checkFalse(rs.next());
stat.execute("DROP TABLE TEST");
}
private void testProcedureColumns() throws Exception {
DatabaseMetaData meta = conn.getMetaData();
ResultSet rs;
......@@ -550,24 +567,24 @@ public class TestMetaData extends TestBase {
testResultSetOrdered(rs,
new String[][] {
{ catalog, Constants.SCHEMA_MAIN, "TEST", "ID", "" + Types.INTEGER, "INTEGER", "10", "10", "0",
"10", "" + DatabaseMetaData.columnNoNulls, "", "", "" + Types.INTEGER, "0", "10", "1",
"10", "" + DatabaseMetaData.columnNoNulls, "", null, "" + Types.INTEGER, "0", "10", "1",
"NO" },
{ catalog, Constants.SCHEMA_MAIN, "TEST", "TEXT_V", "" + Types.VARCHAR, "VARCHAR", "120",
"120", "0", "10", "" + DatabaseMetaData.columnNullable, "", "", "" + Types.VARCHAR,
"120", "0", "10", "" + DatabaseMetaData.columnNullable, "", null, "" + Types.VARCHAR,
"0", "120", "2", "YES" },
{ catalog, Constants.SCHEMA_MAIN, "TEST", "DEC_V", "" + Types.DECIMAL, "DECIMAL", "12", "12",
"3", "10", "" + DatabaseMetaData.columnNullable, "", "", "" + Types.DECIMAL, "0", "12",
"3", "10", "" + DatabaseMetaData.columnNullable, "", null, "" + Types.DECIMAL, "0", "12",
"3", "YES" },
{ catalog, Constants.SCHEMA_MAIN, "TEST", "DATE_V", "" + Types.TIMESTAMP, "TIMESTAMP", "23",
"23", "10", "10", "" + DatabaseMetaData.columnNullable, "", "", "" + Types.TIMESTAMP,
"23", "10", "10", "" + DatabaseMetaData.columnNullable, "", null, "" + Types.TIMESTAMP,
"0", "23", "4", "YES" },
{ catalog, Constants.SCHEMA_MAIN, "TEST", "BLOB_V", "" + Types.BLOB, "BLOB",
"" + Integer.MAX_VALUE, "" + Integer.MAX_VALUE, "0", "10",
"" + DatabaseMetaData.columnNullable, "", "", "" + Types.BLOB, "0",
"" + DatabaseMetaData.columnNullable, "", null, "" + Types.BLOB, "0",
"" + Integer.MAX_VALUE, "5", "YES" },
{ catalog, Constants.SCHEMA_MAIN, "TEST", "CLOB_V", "" + Types.CLOB, "CLOB",
"" + Integer.MAX_VALUE, "" + Integer.MAX_VALUE, "0", "10",
"" + DatabaseMetaData.columnNullable, "", "", "" + Types.CLOB, "0",
"" + DatabaseMetaData.columnNullable, "", null, "" + Types.CLOB, "0",
"" + Integer.MAX_VALUE, "6", "YES" } });
/*
* rs=meta.getColumns(null,null,"TEST",null); while(rs.next()) { int
......
......@@ -1056,11 +1056,11 @@ create memory table orders ( orderid varchar(10), name varchar(20), customer_id
select * from information_schema.columns where table_name = 'ORDERS';
> TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_PRECISION_RADIX NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME TYPE_NAME NULLABLE IS_COMPUTED SELECTIVITY CHECK_CONSTRAINT REMARKS
> ------------- ------------ ---------- ----------- ---------------- -------------- ----------- --------- ------------------------ ---------------------- ----------------- ----------------------- ------------- ------------------ -------------- --------- -------- ----------- ----------- ---------------- -------
> SCRIPT PUBLIC ORDERS COMPLETED 4 NO 3 1 1 1 10 0 Unicode OFF DECIMAL 0 FALSE 50
> SCRIPT PUBLIC ORDERS CUSTOMER_ID 3 YES 12 10 10 10 10 0 Unicode OFF VARCHAR 1 FALSE 50
> SCRIPT PUBLIC ORDERS NAME 2 YES 12 20 20 20 10 0 Unicode OFF VARCHAR 1 FALSE 50
> SCRIPT PUBLIC ORDERS ORDERID 1 YES 12 10 10 10 10 0 Unicode OFF VARCHAR 1 FALSE 50
> SCRIPT PUBLIC ORDERS VERIFIED 5 YES 3 1 1 1 10 0 Unicode OFF DECIMAL 1 FALSE 50
> SCRIPT PUBLIC ORDERS COMPLETED 4 null NO 3 1 1 1 10 0 Unicode OFF DECIMAL 0 FALSE 50
> SCRIPT PUBLIC ORDERS CUSTOMER_ID 3 null YES 12 10 10 10 10 0 Unicode OFF VARCHAR 1 FALSE 50
> SCRIPT PUBLIC ORDERS NAME 2 null YES 12 20 20 20 10 0 Unicode OFF VARCHAR 1 FALSE 50
> SCRIPT PUBLIC ORDERS ORDERID 1 null YES 12 10 10 10 10 0 Unicode OFF VARCHAR 1 FALSE 50
> SCRIPT PUBLIC ORDERS VERIFIED 5 null YES 3 1 1 1 10 0 Unicode OFF DECIMAL 1 FALSE 50
> rows: 5
drop table orders;
......@@ -1466,11 +1466,11 @@ select * from test;
select DOMAIN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, PRECISION, SCALE, TYPE_NAME, SELECTIVITY, CHECK_CONSTRAINT, REMARKS, SQL from information_schema.domains;
> DOMAIN_NAME COLUMN_DEFAULT IS_NULLABLE DATA_TYPE PRECISION SCALE TYPE_NAME SELECTIVITY CHECK_CONSTRAINT REMARKS SQL
> ----------- -------------- ----------- --------- ---------- ----- --------- ----------- --------------------------------------------------------------- ------- ------------------------------------------------------------------------------------------------------------------------------
> EMAIL YES 12 200 0 VARCHAR 50 (POSITION('@', VALUE) > 1) CREATE DOMAIN EMAIL AS VARCHAR(200) CHECK (POSITION('@', VALUE) > 1)
> EMAIL null YES 12 200 0 VARCHAR 50 (POSITION('@', VALUE) > 1) CREATE DOMAIN EMAIL AS VARCHAR(200) CHECK (POSITION('@', VALUE) > 1)
> GMAIL '@gmail.com' YES 12 200 0 VARCHAR 50 ((POSITION('@', VALUE) > 1) AND (POSITION('gmail', VALUE) > 1)) CREATE DOMAIN GMAIL AS VARCHAR(200) DEFAULT '@gmail.com' CHECK ((POSITION('@', VALUE) > 1) AND (POSITION('gmail', VALUE) > 1))
> STRING '' NO 12 255 0 VARCHAR 50 CREATE DOMAIN STRING AS VARCHAR(255) DEFAULT '' NOT NULL
> STRING1 YES 12 2147483647 0 VARCHAR 50 CREATE DOMAIN STRING1 AS VARCHAR
> STRING2 NO 12 2147483647 0 VARCHAR 50 CREATE DOMAIN STRING2 AS VARCHAR NOT NULL
> STRING1 null YES 12 2147483647 0 VARCHAR 50 CREATE DOMAIN STRING1 AS VARCHAR
> STRING2 null NO 12 2147483647 0 VARCHAR 50 CREATE DOMAIN STRING2 AS VARCHAR NOT NULL
> STRING3 '<empty>' YES 12 2147483647 0 VARCHAR 50 CREATE DOMAIN STRING3 AS VARCHAR DEFAULT '<empty>'
> STRING_X '<empty>' YES 12 2147483647 0 VARCHAR 50 CREATE DOMAIN STRING_X AS VARCHAR DEFAULT '<empty>'
> rows: 7
......
select extract(hour from timestamp '2001-02-03 14:15:16');
> 14;
select extract(hour from '2001-02-03 14:15:16');
> 14;
select hour('2001-02-03 14:15:16');
> 14;
CREATE TABLE TEST(A int NOT NULL, B int NOT NULL, C int) ;
ALTER TABLE TEST ADD CONSTRAINT CON UNIQUE(A,B);
ALTER TABLE TEST DROP C;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论