在 Sybase 服务器端语言中,我的代码如何测试它是在链式还是非链式(自动提交)模式下运行?
检查的状态@@TRANCOUNT
并不是真正的结论。
我认为必须有一种方法,例如,JDBC 提供了getAutoCommit,它能够检测连接是否处于自动提交(未链接)模式。但是我如何在存储过程中做到这一点?
我找到了这个问题,但它似乎只回答了 SQL Server。
在 Sybase 服务器端语言中,我的代码如何测试它是在链式还是非链式(自动提交)模式下运行?
检查的状态@@TRANCOUNT
并不是真正的结论。
我认为必须有一种方法,例如,JDBC 提供了getAutoCommit,它能够检测连接是否处于自动提交(未链接)模式。但是我如何在存储过程中做到这一点?
我找到了这个问题,但它似乎只回答了 SQL Server。
我正在阅读Sybase ASE 15.7 文档datetime
中的数据类型描述:
datetime 列包含 1753 年 1 月 1 日到 9999 年 12 月 31 日之间的日期。在支持这种粒度级别的平台上,datetime 值精确到 1/300 秒。
我觉得上面的内容非常令人困惑。首先,这是唯一添加了“在支持这种粒度级别的平台上”的警告的数据类型。这到底是什么意思,我如何确定我的平台是否是“支持这种粒度级别”的平台之一?
此外,我不清楚能够有效地准确存储 1/300 秒意味着什么。我正在使用 JDBC 访问数据库,唯一可能的类型是java.sql.Timestamp。这种类型允许我检索到纳秒的精度。但鉴于在一般情况下除以 300 需要十进制系统中的无限位数字,实际上需要小数纳秒(具有无限十进制数字)来保持表示为 1/300 秒的值。因此,这意味着我无法在不丢失一些精度的情况下获取存储在服务器中的值,但可以忽略不计。
最后,当我执行以下查询时:
SELECT convert(char(32), submission_date, 139) FROM some..table
我看到如下值:
Jan 6 2014 12:36:12.420000
Sep 12 2013 13:44:57.100000
Sep 10 2014 13:47:02.240000
Sep 10 2014 13:47:07.850000
Sep 10 2014 13:47:13.346000
Sep 10 2014 13:47:19.033000
Sep 10 2014 13:47:24.533000
Sep 10 2014 13:47:30.030000
Sep 10 2014 13:47:35.636000
Sep 10 2014 13:47:41.136000
Sep 10 2014 13:47:46.750000
Sep 10 2014 13:47:52.240000
Sep 25 2014 09:01:18.426000
这些值似乎表明只保留了整千分之一秒(而不是 1/300 秒 - 这需要千分之一的小数)。如果是服务器内部存储值“精确到 1/300 秒”的情况,我希望转换为十进制表示法以使用所有可用的小数位(3/300 秒的边缘情况除外,30/300 secs、150/300 secs 和其他一些不需要十进制系统中无限位数的数字)。
我试图了解事务链接和自动提交概念之间的关系。自动提交通常在客户端编程接口中公开。例如在 JDBC 中使用Connection#setAutoCommit方法。
即我想知道是否:
或者
有许多资源表明案例是 1。相同的资源似乎表明unchained
对应于autocommit on
. 例如
这篇文章说:
设置链式关闭(Sybase 中的默认设置,= 设置自动提交)
这个更广泛的帖子同样说:
一些数据库编程接口具有自动提交模式,也称为非链模式。在这种模式下,每条语句都是一个事务,执行后提交。如果您希望在应用程序中使用事务,则需要使用手动提交模式或链式模式。
到目前为止,这是我自己的理解。例如,每当我尝试执行(使用 JDBC)存储过程时,都会遇到以下消息:
java.sql.SQLException:存储过程 'whatever' 只能在非链式事务模式下运行。
…然后在我的代码中设置:
conn.setAutoCommit(true);
…修复了似乎确认确实unchained与autocommit相同的问题。
但是查看Sybase ASE 文档,其中一个内容如下:
默认模式称为非链接模式或 Transact-SQL 模式,需要显式开始事务语句与提交事务或回滚事务语句配对才能完成事务。
这似乎与自动提交完全相反——除非上述文本被理解为具有以下含义:
默认模式,称为 unchained 模式或 Transact-SQL 模式,需要显式开始事务语句与提交事务或回滚事务语句配对,以在一个事务中放置多个语句时完成事务。
最后,我看到这篇文章表明链接和自动提交大多是正交的。
该sp_droptype
过程可用于删除用户定义类型。
所以我sp_droptype
在我的“干净”脚本中有很多这样的调用,我使用sqsh -i
. 但是,sp_droptype
仅当类型确实存在时才可能有条件地调用,或者如果类型不存在则指示它保持沉默。
有没有办法测试一个类型是否存在并且只sp_droptype
在它实际存在时才调用?这将导致更清洁的输出。
在 PostgreSQL 中,可以通过执行以下操作创建具有隐式 CHECK 的用户定义类型:
CREATE DOMAIN OrdinalT AS INTEGER CHECK (value >= 0);
在 Sybase ASE 15.7 中,我认为以下几乎是等价的(除了 CHECK):
sp_addtype OrdinalT, "INTEGER";
如何在 Sybase 中创建用户定义类型定义的 CHECK 部分?
一旦我连接到数据库服务器而不指定特定数据库,例如:
sqsh -Usomeuser -Ssomeserver
......我可以做一个:
select db_name();
…查看该用户的默认数据库。但是这些信息保存在哪里和/或如何查看为每个用户名或登录名配置的默认数据库?
我想在 XML 文档中进行全文搜索。
但是,我无法匹配属性值(如果我提供完整的属性值,包括下例中的:
和/
字符,我会收到语法错误)。另外,我不知道如何为解析器指定我自己的定界符。
下面是SSCCE:
我希望能够选择属性值的最后一个组成部分:attributevalue
并让解析器将:
and识别/
为定界符,因此 yield boo1
, boo2
,some
和attributevalue
作为词位。
DROP TABLE IF EXISTS xmldocument;
CREATE TABLE IF NOT EXISTS xmldocument (
i SERIAL NOT NULL,
content XML NOT NULL
);
ALTER TABLE xmldocument ADD PRIMARY KEY (i);
INSERT INTO xmldocument (content) VALUES
('<a>foo</a>')
,('<a boo=''boo1:boo2:boo3/boo4/some/attributevalue''>foo</a>')
;
-- matches both records as expected
SELECT * FROM xmldocument WHERE to_tsvector(CAST (content AS VARCHAR))@@'foo';
-- no match
SELECT * FROM xmldocument WHERE to_tsvector(CAST (content AS VARCHAR))@@'attributevalue';
-- no match
SELECT * FROM xmldocument WHERE to_tsvector(CAST (content AS VARCHAR))@@'boo2';
-- no match
SELECT * FROM xmldocument WHERE to_tsvector(CAST (content AS VARCHAR))@@'boo4';
至于为什么我不只是使用ILIKE %
等。原因是我需要通过使用 GIN 索引进行优化,我认为在简单的 VARCHAR 值上构建索引是不可能或有意义的。
*接受答案后更新*
根据接受的答案,以下查询均按预期工作:
SELECT * FROM fts.xmldocument WHERE
to_tsvector(regexp_replace(content::text,'[<>/]',' ','g')) @@ to_tsquery('foo');
SELECT * FROM fts.xmldocument WHERE
to_tsvector(regexp_replace(content::text,'[<>/]',' ','g')) @@ to_tsquery('attributevalue');
SELECT * FROM fts.xmldocument WHERE
to_tsvector(regexp_replace(content::text,'[<>/]',' ','g')) @@ to_tsquery('boo2');
SELECT * FROM fts.xmldocument WHERE
to_tsvector(regexp_replace(content::text,'[<>/]',' ','g')) @@ to_tsquery('boo4');
在解决另一个问题时,我注意到在我的 Ubuntu 14.04 系统中有两个postgresql
目录包含一个postgresql.conf
文件:
具有以下目录结构:
$ tree -d /usr/share/postgresql
/usr/share/postgresql
├── 9.3
│ ├── extension
│ ├── man
│ │ ├── man1
│ │ └── man7
│ ├── timezonesets
│ └── tsearch_data
└── 9.4
└── man
├── man1
└── man7
... 和:
$ tree -d /etc/postgresql/9.3/main/
/etc/postgresql/9.3/main/
postgresql.conf
文件位于以下位置:
通过使用SHOW config_file;
,我已经验证了我的服务器正在使用哪个配置文件:
postgres=# SHOW config_file;
config_file
------------------------------------------
/etc/postgresql/9.3/main/postgresql.conf
(1 row)
我的问题是为什么我会postgresql.conf
在两个位置找到该文件,以上是否表明我应该清除一些未使用的安装或其他未使用的工件?
我已按照以下说明进行操作:
http://www.postgresql.org/docs/9.3/static/pgstatstatements.html
...添加以下行的效果:
# postgresql.conf
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 10000
pg_stat_statements.track = all
在文件中postgresql.conf
,然后重新启动服务器,但表pg_stat_statements
仍然不可见:
$ cat /usr/share/postgresql/9.3/postgresql.conf | grep -A3 ^shared_preload_libraries
shared_preload_libraries = 'pg_stat_statements' # (change requires restart)
pg_stat_statements.max = 10000
pg_stat_statements.track = all
$ sudo /etc/init.d/postgresql restart
* Restarting PostgreSQL 9.3 database server [ OK ]
$ psql -U postgres
psql (9.3.10)
Type "help" for help.
postgres=# select count(*) from pg_stat_activity;
count
-------
1
(1 row)
postgres=# select count(*) from pg_stat_statements;
ERROR: relation "pg_stat_statements" does not exist
执行后:
sudo apt-get install postgresql-contrib-9.3
然后做:
$ psql -U postgres
psql (9.4.5, server 9.3.10)
Type "help" for help.
postgres=# create extension pg_stat_statements;
CREATE EXTENSION
postgres=# \dx
List of installed extensions
Name | Version | Schema | Description
--------------------+---------+------------+-----------------------------------------------------------
pg_stat_statements | 1.1 | public | track execution statistics of all SQL statements executed
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(2 rows)
postgres=# \quit
$ sudo /etc/init.d/postgresql restart
* Restarting PostgreSQL 9.3 database server [OK]
...我现在得到:
postgres=# select * from pg_stat_statements ;
ERROR: pg_stat_statements must be loaded via shared_preload_libraries
我正在运行Ubuntu 14.04.03 LTS
。PostgreSQL 与apt-get install
.
在执行时,sudo /etc/init.d/postgresql restart
我得到以下日志跟踪:
$ tail -f /var/log/postgresql/postgresql-9.3-main.log
2015-12-21 11:11:31 EET [23790-2] LOG: received fast shutdown request
2015-12-21 11:11:31 EET [23790-3] LOG: aborting any active transactions
2015-12-21 11:11:31 EET [7231-1] esavo-user@RegTAP FATAL: terminating connection due to administrator command
2015-12-21 11:11:31 EET [23903-5] postgres@postgres FATAL: terminating connection due to administrator command
2015-12-21 11:11:31 EET [23822-7] esavo-user@RegTAP FATAL: terminating connection due to administrator command
2015-12-21 11:11:31 EET [23795-2] LOG: autovacuum launcher shutting down
2015-12-21 11:11:31 EET [23815-1] esavo-user@RegTAP FATAL: terminating connection due to administrator command
2015-12-21 11:11:31 EET [23792-1] LOG: shutting down
2015-12-21 11:11:31 EET [23792-2] LOG: database system is shut down
2015-12-21 11:11:32 EET [16886-1] LOG: database system was shut down at 2015-12-21 11:11:31 EET
2015-12-21 11:11:32 EET [16886-2] LOG: MultiXact member wraparound protections are now enabled
2015-12-21 11:11:32 EET [16885-1] LOG: database system is ready to accept connections
2015-12-21 11:11:32 EET [16890-1] LOG: autovacuum launcher started
2015-12-21 11:11:33 EET [16892-1] [unknown]@[unknown] LOG: incomplete startup packet
这是我的数据库的真实结果。我花了一些时间尝试使用 SSCCE 重现此行为但失败了。下面的最后一个结果是怎么可能的?
SELECT COUNT(*) FROM rr.resource a
--- 15771
SELECT COUNT(*) FROM rr.resource a
NATURAL JOIN rr.interface b
--- 41419
SELECT COUNT(*)
FROM rr.resource a
NATURAL JOIN rr.interface b
NATURAL JOIN rr.interface c
--- 0
最后一个查询中的零 (0) 行计数每次都是一致且可重复的。在我创建的一些示例中,对同一个表添加第二个自然联接两次会产生相同数量的行(正如我所期望的)。那么上述结果怎么可能呢?
passwd
pg_shadow列中的密码是如何编码的?
做一个:
select passwd from pg_shadow;
我看到如下值:
md52c92c858aa1fa12144f1dcbd4ca9c3a0
...这似乎不是我所知道的密码的 MD5 哈希值(显然剥离了前导的“md5”)。哈希也加盐了吗?
我正在遵循 PostgreSQL 安装指南,该指南建议(在首次安装数据库之后)为postgres
用户设置密码:
alter role postgres password '<<super-secret-password>>';
...然后更改pg_hba.conf
文件,以便本地(Unix)套接字的行读取:
local all all md5
... 代替:
local all all trust
在我看来,这只是增加了一层额外的防御,但对于要利用的人来说,local all all trust
他首先必须获得对本地机器的访问权,对吗?
问题 1:我是否理解正确,如果对本地计算机的访问受密码保护(UNIX 密码),那么应该不用担心 a local all all trust
?
此外,同一指南还建议将.pgpass
文件放在我的主文件夹中(我猜是备份脚本无法提示输入密码)。密码以明文形式存储在该~/.pgpass
文件中:
echo 'localhost:5432:*:postgres:<<super-secret-password>>' > .pgpass
chmod 0600 ~/.pgpass
问题 2:那么,使用本地套接字md5
而不是trust
本地套接字有什么好处?如果一个人可以访问本地机器,他也可以读取该.pgpass
文件。我错过了什么吗?
我知道,安装后,PostgreSQL 的 db root 用户(postgres)没有密码:
postgres=# select usename, passwd is null from pg_shadow;
usename | ?column?
----------+----------
postgres | t
(1 row)
...建议将其设置为:
alter role postgres password '<<very-secret>>';
(然后pg_hba.conf
相应地更新文件)
我的问题是:当 user 不需要密码时,用于恢复到以前情况的 SQL 是什么postgres
。
一般来说,我怎样才能删除任何角色的密码要求?我不是在问如何更改密码,而是在问如何删除密码要求(表中的空passwd
列pg_shadow
)。
我知道在 PostgreSQL 中,如果从一个表B
到另一个表有一个多列 FK,A
并且表中的一个或多个 FK 列B
可以为空,那么对于B
这些列的值为实际上是 NULL,不检查表中是否存在相应的行A
(因为主键列不能为空):
但是,这是 PostgreSQL 特定的还是在 SQL 标准中?(使用 SQL Fiddle 进行实验,似乎 MS SQL Server 和 MySQL 的行为方式相同)。
我有一个应用程序(作为其逻辑的一部分)在插入数据库之前修剪字符串并用 NULL 替换空字符串。我想确保执行此操作的一种方法是在每个具有VARCHAR
, TEXT
(或类似)列的表上编写一个 CHECK 。
假设一个人不能或不想这样做,有一种方法可以编写一个简单的通用 SQL 查询(从数据库的元数据中获取表和列名),以检查数据库中的任何文本列是否包含空字符串?
SSCCE:以下脚本:
$ cat test.sql
CREATE TABLE public.foo (
loop INTEGER
);
CREATE OR REPLACE FUNCTION public.foo_fun(loop INTEGER) RETURNS BOOLEAN AS $$
SELECT TRUE;
$$ LANGUAGE SQL;
CREATE OR REPLACE FUNCTION public.foo_tr_fun() RETURNS TRIGGER AS $$
DECLARE
fRV BOOLEAN;
BEGIN
SELECT public.foo_fun(NEW.loop) INTO fRV;
IF fRV THEN
RETURN NEW;
ELSE
RAISE EXCEPTION 'bar';
END IF;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER foo_tr AFTER INSERT OR UPDATE ON public.foo
FOR EACH ROW
EXECUTE PROCEDURE public.foo_tr_fun();
...我运行的是:
psql -v ON_ERROR_STOP=1 --quiet -X -U some-user -d some-db -f test.sql
...当我尝试将一行插入foo
(from psql
) 时:
$ psql -U some-user some-db
psql (9.1.14)
Type "help" for help.
RegTAP=> SELECT * FROM public.foo;
loop
------
(0 rows)
RegTAP=> INSERT INTO public.foo(loop) VALUES(0);
ERROR: record "new" has no field "loop"
LINE 1: SELECT public.foo_fun(NEW.loop)
^
QUERY: SELECT public.foo_fun(NEW.loop)
CONTEXT: PL/pgSQL function "foo_tr_fun" line 5 at SQL statement
RegTAP=>
我发出以下 DDL:
CREATE TABLE foo
(
loopa INTEGER,
loop INTEGER
);
然后,检查服务器中的 DDL(使用像DbVisualizer这样的客户端工具- 抱歉不知道直接生成它的查询)我看到以下内容:
CREATE TABLE
foo
(
loopa INTEGER,
LOOP INTEGER
);
观察 named 列大小写的变化,而 named 列loop
则没有loopa
。查看SQL关键字 loop
列表似乎没有关键字。那么,为什么会有这种选择性的改变呢?
这似乎与我在尝试访问loop
表中的列时遇到的问题有关:
Exception in thread "main" org.postgresql.util.PSQLException: ERROR: record "new" has no field "loop"
(无论触发器函数中的代码是否以NEW.LOOP
或访问字段,我都会得到相同的错误NEW.loop
)
更新
大写字母似乎是 DbVisualizer 的产物。psql
显示:
psql (9.1.13)
Type "help" for help.
foo-test=> \dS+ foo
Table "test.foo"
Column | Type | Modifiers | Storage | Description
--------+---------+-----------+---------+-------------
loopa | integer | | plain |
loop | integer | | plain |
Has OIDs: no
然而,这仍然不能解释为什么 PostgreSQL 引擎显然不允许我的触发器访问NEW.loop
. 当我将列(和触发代码)重命名为loopi
一切似乎工作正常。因此,除了 DbVisualizer 故障之外,这里可能还有更深层次的原因在起作用。稍后我将尝试创建一个 SSCCE。
更新 2
触发问题的 SSCCE 已在此处创建。
这显然是一个SSCCE。
我有一个inventory
表格,其中包含numOfItems
在任何给定日期( )仓库中的项目数量( inventoryDate
)。两者都是整数,以保持简单:
CREATE TABLE inventory(inventoryDate INTEGER, numOfItems INTEGER);
ALTER TABLE inventory ADD PRIMARY KEY (inventoryDate);
现在我有一些条目:
INSERT INTO inventory(inventoryDate, numOfItems) VALUES(1,250),(2,275)
上面说的是,1
仓库里准时有 250 件物品,准时2
有 275 件。
现在我想测试一下,在最晚的日期,仓库中的商品数量是否超过了 1000:
SELECT 1000<(SELECT numOfItems FROM inventory ORDER BY inventoryDate DESC LIMIT 1)
以上似乎工作。但是,在inventory
表中根本没有条目的边缘情况下,它不起作用:
DELETE FROM inventory;
SELECT 1000<(SELECT numOfItems FROM inventory ORDER BY inventoryDate DESC LIMIT 1)
...返回:
?column?
(null)
我想将根本没有条目的边缘情况视为表示零 (0) 项。我知道我总是可以inventory
用值为零的假第一个条目来初始化表,但就像我说的那样,这是一个 SSCCE(在我的真实情况下,这个表实际上是一个我不想修改的视图)。
所以我最终写了这样的查询:
WITH cte AS (SELECT numOfItems FROM inventory ORDER BY inventoryDate DESC LIMIT 1)
SELECT 1000 < (
CASE
WHEN NOT EXISTS(SELECT 1 FROM cte) THEN 0
ELSE (SELECT numOfItems FROM cte)
END)
以上似乎确实有效。但是,有没有更惯用的方法?类似于 aCOALESCE
但是对于空结果集而不是 null?
我正在使用pg_dump(纯文本格式)转储我的 Postgres 数据库,然后使用psql(带有-f
选项)简单地恢复它。
这引出了一个问题:不使用pg_restore似乎是一个专门的恢复工具(与 generic 相比),我是否遗漏了任何东西psql
?
pg_dump
我可以通过使用参数来控制诸如禁用触发器之类的选项。那么,是pg_restore
用来做什么的呢?非纯文本转储格式 ?