我有一个具有 type属性的punctures
表,我需要插入一条开放式记录,下限为当前时间 ( )。我试过extent
tsrange
extent
now()
INSERT INTO punctures(extent)
VALUES(tsrange(now(), ));
及其变体,但都会产生错误。
我如何定义tsrange
?
我有一个具有 type属性的punctures
表,我需要插入一条开放式记录,下限为当前时间 ( )。我试过extent
tsrange
extent
now()
INSERT INTO punctures(extent)
VALUES(tsrange(now(), ));
及其变体,但都会产生错误。
我如何定义tsrange
?
因此,我们使用数据库服务器的主力已经有 7 年多了,去年我们开始逐步使用一台新服务器,它在各方面都本质上更好,一次转换一个数据库。特别是有一个数据库我们转移到了新服务器,但情况变得很糟糕......
即使在中低负载下,查询也会开始超时,该数据库和其他已转换的数据库的性能几乎在各个方面都明显变慢,直到我们转换回原始服务器。一旦我们这样做了,新服务器上的性能就稳定下来,并且问题数据库在原始服务器上也很好。
一些具体细节会有所帮助!
服务器配置几乎相同,除了由于硬件差异(最大 RAM)而有意义的地方。以下是截图:
*新服务器上未启用启用包含的数据库,但是,我们不使用此功能。
**在评论开始之前,我意识到 CTFP 太离谱了,那完全是另一个蜡球。
特别是,在审查我们的监控工具时,我们在比较从 sys.dm_os_performance_counters 获得的以下指标时注意到不成比例的值:
如果有帮助的话,很乐意提供更多详细信息/图表。
所讨论的数据库大小适中,但对我们来说很大(120 GB),但 OLTP 应用程序中有许多活跃的写入者。特别是这个数据库涉及很多页面拆分。
从学术上讲,新服务器的一切都应该能够处理旧服务器的负载,然后是一些。
所有这些信息都是为了问这些问题:
预先感谢您加入我的疯狂!
更新1
我们每晚运行 Ola Hallengren 令人惊叹的SQL Server 索引和统计维护脚本,以 5% 碎片重新组织每个表,以 30% 碎片重建并更新 INDEX 统计信息。这是由 SQL 代理在每台服务器上运行的,没有错误。
更新2
在花了一些时间建立在不影响客户的情况下复制我们设置的负载的方法之后,我们开始测试各种理论。获胜者是@StrayCatDBA,他通过电源设置调用了它。平衡的电源选项最终停放了我们的许多核心,服务器从未承受足够的负载来克服这种限制,但这足以驱动服务器挣扎以影响工作负载。
我感谢所有花时间插话的人。有些反馈在短期内很有帮助,有些反馈有助于开始重构我们一些更“激进”的查询(以及补偿所需的实践) 。
Oracle 19c 有没有办法监控索引?
我已打开索引监控
ALTER INDEX my_index_i MONITORING USAGE;
使用下面的查询可以大致了解何时使用索引:
SELECT index_name,
table_name,
monitoring,
used,
start_monitoring,
end_monitoring
FROM dba_object_usage
WHERE index_name = 'name'
AND owner = 'name'
ORDER BY index_name;
SELECT name, owner, TO_CHAR(last_used, 'YYYY-MM-DD HH24:MI:SS') AS "Last Used"
FROM dba_index_usage
WHERE name = 'name';
问题是,我仍然无法判断一个索引一天被使用了多少次,以及在什么时间被使用?
有没有办法/查询来监控这种情况?
PS 我知道触发器,但我正在寻找替代方案 - 如果我没有找到替代方案,那么触发器就是!
提前致谢!
tl;dr:何时使用array_agg
数组子查询的横向连接?
语境:
create table t_zipcode ( zipcode text primary key, location geography );
create table t_user ( id text primary key, zipcode text references t_zipcode);
我想设计一个查询,获取每个用户的所有“附近”邮政编码,例如 20 公里范围内的邮政编码。我的第一次尝试是这样的:
select u.id, z.zipcode, z.location, array_agg(zz.zipcode order by zz.zipcode) as nearby_zipcodes
from t_user u
join t_zipcode z on u.zipcode = z.zipcode
left join t_zipcode zz on st_dwithin(z.location, zz.location, 20000)
group by u.id, z.zipcode, z.location
order by u.id;
返回的结果如下:
+------------------------------------+-------+--------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|id |zipcode|location |nearby_zipcodes |
+------------------------------------+-------+--------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|0233684d-d2d8-4fdc-863f-08c6aac79d92|81001 |0101000020E6100000C4245CC823225AC025E7C41EDA254340|{81001,81003,81006,81008,81025} |
|0e59fd58-00a5-442e-a21e-16ab1f4d2f65|85226 |0101000020E6100000506EDBF7A8005CC016A243E048A04040|{85034,85040,85041,85042,85044,85045,85048,85121,85202,85224,85225,85226,85248,85282,85283,85284,85286,85339} |
|13f26eca-bda0-4b8f-bcff-c95cceee3421|81001 |0101000020E6100000C4245CC823225AC025E7C41EDA254340|{81001,81003,81006,81008,81025} |
|2d69e6bd-e0f0-40aa-ba3a-0e157fff46ff|81001 |0101000020E6100000C4245CC823225AC025E7C41EDA254340|{81001,81003,81006,81008,81025} |
|4bd8e913-7a75-4028-8254-faebf043f629|81001 |0101000020E6100000C4245CC823225AC025E7C41EDA254340|{81001,81003,81006,81008,81025} |
|627897e0-595c-4d21-b1b1-8dd43f21dee7|85033 |0101000020E6100000DAC69FA86C0D5CC08E78B29B19BF4040|{85003,85004,85006,85007,85009,85012,85013,85014,85015,85016,85017,85019,85020,85021,85023,85029,85031,85033,85034,85035,85037,85040,85041,85043,85051,85053,85064,85301,85302,85303,85304,85305,85306,85307,85308,85309,85323,85335,85340,85345,85351,85353,85363,85378,85379,85381,85382,85392,85395} |
|6353efe7-b0e0-42a2-b5fd-f38b7c8e27ad|81001 |0101000020E6100000C4245CC823225AC025E7C41EDA254340|{81001,81003,81006,81008,81025} |
|6efad24b-10a7-4ac7-b91a-8842bca70c06|81001 |0101000020E6100000C4245CC823225AC025E7C41EDA254340|{81001,81003,81006,81008,81025} |
|7f1fe1d1-e2cd-44b9-85f0-b3b888823a20|85305 |0101000020E6100000BF7D1D3867105CC0D2C6116BF1C34040|{85003,85004,85007,85009,85012,85013,85014,85015,85017,85019,85020,85021,85023,85029,85031,85033,85035,85037,85043,85051,85053,85080,85301,85302,85303,85304,85305,85306,85307,85308,85309,85323,85335,85340,85345,85351,85353,85355,85363,85373,85374,85375,85378,85379,85381,85382,85388,85392,85395} |
|9c238c4a-712b-4b10-a91d-6c3548ae59bc|86001 |0101000020E6100000054F2157EAE85BC0D6AA5D13D2A44140|{86001,86011,86015} |
|ace88100-9ecd-4931-a617-b8d8b091470e|85007 |0101000020E6100000CB30EE06D1055CC0AA9D616A4BB94040|{85003,85004,85006,85007,85008,85009,85012,85013,85014,85015,85016,85017,85018,85019,85020,85021,85028,85029,85031,85033,85034,85035,85037,85040,85041,85042,85043,85044,85045,85048,85051,85064,85251,85253,85257,85281,85282,85283,85284,85301,85302,85303,85304,85305,85353} |
|bf96321b-be2e-4ef9-801e-9ee82ce693f4|81001 |0101000020E6100000C4245CC823225AC025E7C41EDA254340|{81001,81003,81006,81008,81025} |
|d787537e-a3fa-4267-b313-71b2c07027fe|81001 |0101000020E6100000C4245CC823225AC025E7C41EDA254340|{81001,81003,81006,81008,81025} |
|ea8d074d-adb1-4c45-bd02-b6b57f5a6604|41091 |0101000020E61000005B0A48FB1F2F55C063D009A183744340|{41005,41018,41030,41042,41051,41080,41091,41092,41094,41095,47020,47038,47040} |
|f925949e-6a5e-4e2c-9591-60f05f42ccb1|81001 |0101000020E6100000C4245CC823225AC025E7C41EDA254340|{81001,81003,81006,81008,81025} |
|fc47120d-d3da-4847-8134-0eca87708467|98102 |0101000020E61000001C78B5DC99945EC09A7CB3CD8DD14740|{98004,98005,98006,98007,98008,98011,98020,98021,98028,98033,98034,98036,98039,98040,98043,98052,98056,98057,98072,98101,98102,98103,98104,98105,98106,98107,98108,98109,98110,98112,98115,98116,98117,98118,98119,98121,98122,98125,98126,98133,98134,98136,98144,98146,98154,98155,98164,98168,98174,98177,98178,98195,98199,98342,98353}|
+------------------------------------+-------+--------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
这是仅包含 16 个用户并在邮政编码位置列上使用索引的分析计划:
+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
|QUERY PLAN |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
|GroupAggregate (cost=85365.87..86252.54 rows=35467 width=112) (actual time=1.932..2.474 rows=16 loops=1) |
| Output: u.id, z.zipcode, z.location, array_agg(zz.zipcode ORDER BY zz.zipcode) |
| Group Key: u.id, z.zipcode, z.location |
| -> Sort (cost=85365.87..85454.53 rows=35467 width=112) (actual time=1.887..1.913 rows=277 loops=1) |
| Output: u.id, z.zipcode, z.location, zz.zipcode |
| Sort Key: u.id, z.zipcode, z.location |
| Sort Method: quicksort Memory: 53kB |
| -> Nested Loop Left Join (cost=0.69..81507.59 rows=35467 width=112) (actual time=0.197..1.641 rows=277 loops=1) |
| Output: u.id, z.zipcode, z.location, zz.zipcode |
| -> Nested Loop (cost=0.29..719.73 rows=1070 width=80) (actual time=0.043..0.136 rows=16 loops=1) |
| Output: u.id, z.zipcode, z.location |
| Inner Unique: true |
| -> Seq Scan on pg_temp.t_user u (cost=0.00..20.70 rows=1070 width=48) (actual time=0.017..0.021 rows=16 loops=1) |
| Output: u.id, u.zipcode |
| -> Index Scan using test_idx_user_zip on pg_temp.t_zipcode z (cost=0.29..0.65 rows=1 width=64) (actual time=0.006..0.006 rows=1 loops=16)|
| Output: z.zipcode, z.location |
| Index Cond: (z.zipcode = u.zipcode) |
| -> Index Scan using test_idx_zip_geo on pg_temp.t_zipcode zz (cost=0.40..75.47 rows=3 width=64) (actual time=0.040..0.089 rows=17 loops=16) |
| Output: zz.zipcode, zz.location |
| Index Cond: (zz.location && _st_expand(z.location, '20000'::double precision)) |
| Filter: st_dwithin(z.location, zz.location, '20000'::double precision, true) |
| Rows Removed by Filter: 8 |
|Query Identifier: -2358650375080684395 |
|Planning Time: 0.421 ms |
|Execution Time: 2.649 ms |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
然后,我使用横向连接尝试了类似的解决方案,这产生了完全相同的结果:
select u.id, z.zipcode, z.location, t.nearby_zipcodes
from t_user u
join t_zipcode z on u.zipcode = z.zipcode
cross join lateral (select array(select zz.zipcode
from t_zipcode zz
where st_dwithin(z.location, zz.location, 20000)
order by zz.zipcode) as nearby_zipcodes
) t
order by u.id;
令我惊讶的是,它的性能稍好一些:
+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
|QUERY PLAN |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
|Sort (cost=85823.88..85826.55 rows=1070 width=112) (actual time=1.828..1.830 rows=16 loops=1) |
| Output: u.id, z.zipcode, z.location, ((SubPlan 1)) |
| Sort Key: u.id |
| Sort Method: quicksort Memory: 30kB |
| -> Nested Loop (cost=0.29..85770.04 rows=1070 width=112) (actual time=0.319..1.809 rows=16 loops=1) |
| Output: u.id, z.zipcode, z.location, (SubPlan 1) |
| Inner Unique: true |
| -> Seq Scan on pg_temp.t_user u (cost=0.00..20.70 rows=1070 width=48) (actual time=0.012..0.016 rows=16 loops=1) |
| Output: u.id, u.zipcode |
| -> Index Scan using test_idx_user_zip on pg_temp.t_zipcode z (cost=0.29..0.65 rows=1 width=64) (actual time=0.006..0.006 rows=1 loops=16) |
| Output: z.zipcode, z.location |
| Index Cond: (z.zipcode = u.zipcode) |
| SubPlan 1 |
| -> Sort (cost=79.48..79.49 rows=3 width=32) (actual time=0.101..0.102 rows=17 loops=16) |
| Output: zz.zipcode |
| Sort Key: zz.zipcode |
| Sort Method: quicksort Memory: 25kB |
| -> Index Scan using test_idx_zip_geo on pg_temp.t_zipcode zz (cost=0.40..79.45 rows=3 width=32) (actual time=0.032..0.080 rows=17 loops=16)|
| Output: zz.zipcode |
| Index Cond: (zz.location && _st_expand(z.location, '20000'::double precision)) |
| Filter: st_dwithin(z.location, zz.location, '20000'::double precision, true) |
| Rows Removed by Filter: 8 |
|Query Identifier: 8776498431209157273 |
|Planning Time: 0.257 ms |
|Execution Time: 1.892 ms |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
我的印象是,如果可能的话,一般应该避免横向连接,是否有一个我没有注意到的缺点?
我有一个非常简单的表 SQL 表(目前是 Azure SQL,如果重要的话,可能会留在那里或最终出现在本地 SQL Server 19 实例中),大约 100,000 条记录,主要用于读取,但会逐渐写入。
CREATE TABLE [dbo].[xCatalog](
[catalogID] [int] IDENTITY(1,1) NOT NULL,
[title] [nvarchar](255) NOT NULL,
[dateA] [datetime] NULL,
[dateB] [datetime] NULL,
[textA] [nvarchar](25) NULL,
[textB] [nvarchar](255) NULL,
[textC] [nvarchar](255) NULL,
CONSTRAINT [PK_xCatalog] PRIMARY KEY CLUSTERED
(
[catalogID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
值得注意的是[title] nvarchar(255)字段,该字段将是用户使用以下格式的查询主要搜索的内容,使用“ocean”作为示例 [title] 搜索词
SELECT TOP(500) [catalogID],[title],[dateA],[dateB],[textA],[textB],[textC]
FROM [dbo].[xCatalog]
WHERE ([title] LIKE '%ocean%')
ORDER BY [catalogID] ASC
它运行得相当不错,1-3 秒,但我真的很想深入研究如何/是否改进它,因为坦率地说,我对索引和其他优化等内容只有表面的了解。
查询是由前端程序生成的,我不相信我可以更改,因此为什么它选择按键排序的有限数量来返回虚拟滚动,以及为什么我不探索用 Contains 或其他内容替换 LIKE像那样。
因此,我真的试图从数据库方面来解决这个问题,只是了解最佳实践是什么,以及人们对这种情况的想法,即使用哪种索引,或者是否可以切换到列存储(概率太小?)等等。我们还使用基本层 Azure SQL 数据库,因此对于这种操作,我们可能会从稍微提高它中受益。
任何类似的东西,这样我就可以知道它的未来,并能够自信地解释我已经做了 x 或 y 来帮助它,但也许通配符搜索大文本有时很昂贵,所以我的期望应该是什么。
如果有帮助的话,我会加入简单的执行计划:
谢谢大家的意见!我知道还有很多类似的问题,我会继续研究,但有时感觉它们略有不同,我想问也有什么坏处。
我在撤销权限时遇到问题,导致我无法删除用户
select usename, acl.*
from pg_default_acl as acl join pg_user on usesysid = defacluser
where usename = 'user1';
给我:
|usename|defacluser|defaclnamespace|defaclobjtype|defaclacl |
|-------|----------|---------------|-------------|----------------------|
|user1 |143 |0 |r |{user1=awdRxt/user1}|
使用亚马逊 ( ) 提供的视图,v_get_obj_priv_by_user
我执行此操作以获取具有该用户权限的架构/数据库:
select 'alter table '+schemaname+'.'+tablename+' owner to y;' from pg_tables where tableowner like 'user1';
select distinct 'revoke all on schema '+schemaname+' from user1;' from admin.v_get_obj_priv_by_user where usename like 'user1';
select distinct 'revoke all on all tables in schema '+schemaname+' from user1;' from admin.v_get_obj_priv_by_user where usename like 'user1'
从之前的查询中得到了这 2 个回复
revoke all on schema xxx from user1;
revoke all on all tables in schema xxx from user1;
我运行它们,没有错误,但权限仍然存在,并且使用的查询v_get_obj_priv_by_user
不断返回相同的结果。
显然,当我稍后尝试删除用户时,会出现以下错误:
SQL 错误 [2BP01]:错误:无法删除用户“user1”,因为某些对象依赖于它详细信息:属于用户 user1 的新关系的默认权限的所有者
知道我做错了什么吗?谢谢!
我不是 SQL 方面的专家,所以我需要社区的帮助。
我有以下简化表格。
CREATE TABLE "Keyspace" (
"id" SERIAL NOT NULL,
"tenantId" INTEGER NOT NULL,
"name" TEXT NOT NULL,
CONSTRAINT "Keyspace_pkey" PRIMARY KEY ("id")
);
CREATE TABLE "Project" (
"id" SERIAL NOT NULL,
"tenantId" INTEGER NOT NULL,
"name" TEXT NOT NULL,
"keyspaceId" INTEGER NOT NULL,
CONSTRAINT "Project_pkey" PRIMARY KEY ("id")
);
CREATE TABLE "Entry" (
"id" SERIAL NOT NULL,
"tenantId" INTEGER NOT NULL,
"projectId" INTEGER NOT NULL,
CONSTRAINT "Entry_pkey" PRIMARY KEY ("id")
);
CREATE TABLE "KeyspaceEntry" (
"keyspaceId" INTEGER NOT NULL,
"entryId" INTEGER NOT NULL,
"number" INTEGER NOT NULL
);
一Entry
只能是一Keyspace
。这是通过Entry
-> Project
->Keyspace
引用强制执行的。
一个Keyspace
会有很多Entries
。
重要的字段是KeyspaceEntry.number
. 这是同一密钥空间中每个条目的自动递增编号。
例子:
1
, 2
,3
1
,2
number=4
.我需要number
在同一事务中实现 Entry 和 KeyspaceEntry 的原子插入并递增。
注意:可能看起来没有必要拥有 KeyspaceEntry 表,因为您可以简单地将number
属性添加到 Entry,但这是一个简化的模型。当条目移动到不同键空间下的不同项目时,我希望拥有所有键空间-条目关系的历史记录。
另一种选择是创建历史表但保留实际Entry.number
属性。它可能更适合查询条目(它将用于通过 KeyspaceID+EntryNumber 选择单个条目),我稍后也可能会考虑这一点。如果您对此设计变更有意见,请分享。
我正在使用 PostgreSQL 16
我们有一个数据库服务器,其中测试数据库每天 22:00 都会通过生产数据库的备份进行“刷新”。
恢复后的第一个备份是差异备份,因为我们使用的是交换机ChangeBackupType = Y
。
我们的CleanupTime
参数设置为 48 小时,这对于完整备份和 TLog 备份效果很好。
但是,该CleanupTime
参数不适用于由于ChangeBackupType
设置为而创建的差异备份Y
。
有什么想法问题出在哪里吗?我们没有明确使用差异备份作业,因此CleanupTime
我无法设置。
定义完整备份
sqlcmd -E -S $(ESCAPE_SQUOTE(SRVR)) -d aspMaintenance -Q "EXECUTE [dbo].[DatabaseBackup] @Databases = 'ALL_DATABASES', @BackupType = 'FULL', @NumberOfFiles = 1, @Verify = 'N', @CleanupTime = 42, @CheckSum = 'Y', @DirectoryStructure = '{DatabaseName}{DirectorySeparator}{BackupType}_{Partial}_{CopyOnly}', @LogToTable = 'Y'" -b
定义日志备份
sqlcmd -E -S $(ESCAPE_SQUOTE(SRVR)) -d aspMaintenance -Q "EXECUTE [dbo].[DatabaseBackup] @Databases = 'ALL_DATABASES', @ChangeBackupType = 'Y', @BackupType = 'LOG', @Verify = 'N', @CleanupTime = 48, @CheckSum = 'Y', @DirectoryStructure = '{DatabaseName}{DirectorySeparator}{BackupType}_{Partial}_{CopyOnly}', @LogToTable = 'Y'" -b
我一直认为CONCAT函数实际上是+(字符串连接)的包装,并带有一些额外的检查,以使我们的生活更轻松。
我还没有找到任何关于这些功能是如何实现的内部细节。至于性能,当数据在循环中连接时,调用似乎会产生开销CONCAT
(这似乎很正常,因为有额外的 NULL 句柄)。
几天前,一位开发人员修改了一些字符串连接代码(从+
到 ,CONCAT)
因为不喜欢语法并告诉我它变得更快。
为了检查情况,我使用了以下代码:
DECLARE @V1 NVARCHAR(MAX)
,@V2 NVARCHAR(MAX)
,@V3 NVARCHAR(MAX);
DECLARE @R NVARCHAR(MAX);
SELECT @V1 = REPLICATE(CAST('V1' AS NVARCHAR(MAX)), 50000000)
,@V2 = REPLICATE(CAST('V2' AS NVARCHAR(MAX)), 50000000)
,@V3 = REPLICATE(CAST('V3' AS NVARCHAR(MAX)), 50000000);
这是变体一:
SELECT @R = CAST('' AS NVARCHAR(MAX)) + '{some small text}' + ISNULL(@V1, '{}') + ISNULL(@V2, '{}') + ISNULL(@V3, '{}');
SELECT LEN(@R); -- 1200000017
这是变体二:
SELECT @R = CONCAT('{some small text}',ISNULL(@V1, '{}'), ISNULL(@V2, '{}'), ISNULL(@V3, '{}'))
SELECT LEN(@R); -- 1200000017
对于较小的字符串,没有差异。在某些时候,CONCAT
变体会变得更快:
我想知道有人可以分享一些内部结构或解释其行为,因为似乎可能存在一条规则,最好使用CONCAT
.
版本:
Microsoft SQL Server 2022 (RTM-CU8) (KB5029666) - 16.0.4075.1 (X64) 2023 年 8 月 23 日 14:04:50 版权所有 (C) 2022 Windows Server 2019 Standard 10.0(内部版本 17763)上的 Microsoft Corporation 标准版(64 位) :)(管理程序)
确切的脚本如下所示:
DECLARE @V1 NVARCHAR(MAX)
,@V2 NVARCHAR(MAX)
,@V3 NVARCHAR(MAX);
DECLARE @R NVARCHAR(MAX);
SELECT @V1 = REPLICATE(CAST('V1' AS NVARCHAR(MAX)), 50000000)
,@V2 = REPLICATE(CAST('V2' AS NVARCHAR(MAX)), 50000000)
,@V3 = REPLICATE(CAST('V3' AS NVARCHAR(MAX)), 50000000);
--SELECT @R = CAST('' AS NVARCHAR(MAX)) + '{some small text}' + ISNULL(@V1, '{}') + ISNULL(@V2, '{}') + ISNULL(@V3, '{}'); -- 00:00:45 -- 00:01:22 -- 00:01:20
--SELECT LEN(@R); -- 300000017
SELECT @R = CONCAT('{some small text}',ISNULL(@V1, '{}'), ISNULL(@V2, '{}'), ISNULL(@V3, '{}')) -- 00:00:11 -- 00:00:16 -- 00:00:10
SELECT LEN(@R); -- 300000017
我正在更改 REPLICATE 函数的最后一个参数,以便为连接生成更大的字符串。然后,我将每个变体执行三次。
给出下表:
CREATE TABLE #a
(
MyInt INT
)
INSERT INTO #a VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
CREATE TABLE #b
(
MyVarchar VARCHAR(10)
)
INSERT INTO #b VALUES('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('ten')
如果我运行以下查询;
SELECT *
FROM #a
LEFT JOIN #b
ON #a.MyInt = #b.MyVarchar
SQL Server 必须执行隐式转换,因为#a.MyInt
和#b.MyVarchar
是不匹配的数据类型。由于数据类型优先级,具有最低类型优先级 (#b.MyVarchar) 的列将转换为较高优先级 (INT) 的类型
这意味着上面的查询等效于
SELECT *
FROM #a
LEFT JOIN #b
ON #a.MyInt = CONVERT(INT,#b.MyVarchar)
两者都失败,因为其中某个值#b.MyVarchar
对于列来说是无效值INT
。
我的问题是为什么 的VARCHAR
优先级低于INT
?如果是相反的情况,隐式转换将会成功,但我们会得到一个错误的查询。为什么错误比成功执行更可取?我的猜测是,这对于 SQL Server 来说更像是一种“防御”机制 - 它更喜欢错误,因此需要用户明确决定他们想要做什么,而不是在用户不知情的情况下给出可能意外的查询结果。意识到?