标签: t-sql

为什么“SELECT POWER(10.0, 38.0);” 抛出算术溢出错误?

我正在更新我的IDENTITY溢出检查脚本以考虑DECIMALNUMERIC IDENTITYcolumns

作为检查的一部分,我计算每一IDENTITY列的数据类型范围的大小;我用它来计算该范围的百分比已用完。因为DECIMALNUMERIC 该范围的大小2 * 10^p - 2p是精度在哪里。

我用DECIMALNUMERIC IDENTITY列创建了一堆测试表,并尝试按如下方式计算它们的范围:

SELECT POWER(10.0, precision)
FROM sys.columns
WHERE 
       is_identity = 1
   AND type_is_decimal_or_numeric
;
Run Code Online (Sandbox Code Playgroud)

这引发了以下错误:

Msg 8115, Level 16, State 6, Line 1
Arithmetic overflow error converting float to data type numeric. 
Run Code Online (Sandbox Code Playgroud)

我将它缩小到IDENTITY类型的列DECIMAL(38, 0)(即具有最大精度),然后我POWER()直接尝试对该值进行计算。

以下所有查询

SELECT POWER(10.0, 38.0);
SELECT CONVERT(FLOAT, (POWER(10.0, 38.0)));
SELECT CAST(POWER(10.0, 38.0) …
Run Code Online (Sandbox Code Playgroud)

sql-server-2008 sql-server datatypes t-sql type-conversion

16
推荐指数
2
解决办法
1万
查看次数

如果不存在,则通过代码创建新函数

我想在我的数据库中通过脚本创建新函数。脚本代码如下:

IF Exists(Select * From sys.sysobjects A Where A.name =N'fn_myfunc' and xtype=N'FN') return;

CREATE FUNCTION fn_myfunc ()
returns varchar(10)
AS Begin
...
End
Run Code Online (Sandbox Code Playgroud)

但是当我执行上面的脚本时,SQL Server 返回一个错误:

'CREATE FUNCTION' must be the first statement in a query batch.
Run Code Online (Sandbox Code Playgroud)

sql-server t-sql sql-server-2008-r2 functions

16
推荐指数
1
解决办法
4万
查看次数

为什么 CTE 应该以分号开头?

我只是在看StackOverflow上的一篇文章,其中 Aaron Bertrand 建议使用 CTE 而不是数字表,这是执行手头任务的一种优雅方式。我的问题是,为什么 CTE 的第一行以分号开头?

;WITH n AS (SELECT TOP (10000) n FROM 
  (SELECT n = ROW_NUMBER() OVER
    (ORDER BY s1.[object_id])
    FROM sys.all_objects AS s1
    CROSS JOIN sys.all_objects AS s2
  ) AS x ORDER BY n
)
SELECT n FROM n ORDER BY n; -- look ma, no gaps!
Run Code Online (Sandbox Code Playgroud)

这是为了确保 WITH 语句不会被解析为以前的内容SELECT或其他内容吗?我在 SQL Server 2005 BOL 中没有看到关于在 WITH 之前使用分号的内容。

sql-server syntax cte t-sql

16
推荐指数
3
解决办法
1万
查看次数

强制索引假脱机

我知道出于性能原因应该避免它,但我试图展示一个条件,它显示为演示如何确保它不会出现。

但是,我最终得到了缺少索引警告,但优化器选择不创建临时索引。

我正在使用的查询是

SELECT 
    z.a
FROM dbo.t5 AS z WITH(INDEX(0))
WHERE 
    EXISTS 
    (
        SELECT y.a 
        FROM dbo.t4 AS y
        WHERE y.a = z.a
    )
OPTION (MAXDOP 1);
Run Code Online (Sandbox Code Playgroud)

表模式是:

CREATE TABLE dbo.t4
(
    a   integer NULL,
    b   varchar(1000) NULL,
    p   varchar(100) NULL
);

CREATE TABLE dbo.t5
(
    a   integer NULL,
    b   varchar(1000) NULL
);

CREATE UNIQUE CLUSTERED INDEX c1 
ON dbo.t5 (a);
Run Code Online (Sandbox Code Playgroud)

两个表都有 10,000 行,您可以使用以下方法进行模拟:

UPDATE STATISTICS dbo.t4 
WITH 
    ROWCOUNT = 10000, 
    PAGECOUNT = 1000;

UPDATE STATISTICS dbo.t5 
WITH 
    ROWCOUNT = …
Run Code Online (Sandbox Code Playgroud)

t-sql execution-plan sql-server-2012 index-spool

16
推荐指数
1
解决办法
1724
查看次数

如何使用执行计划优化 T-SQL 查询

我有一个 SQL 查询,我花了两天时间尝试使用试错法和执行计划进行优化,但无济于事。请原谅我这样做,但我会在这里发布整个执行计划。我已经努力使查询和执行计划中的表名和列名通用,既为了简洁又为了保护我公司的 IP。可以使用SQL Sentry Plan Explorer打开执行计划。

我已经完成了大量的 T-SQL,但是使用执行计划来优化我的查询对我来说是一个新领域,我真的试图了解如何去做。所以,如果有人能帮我解决这个问题并解释如何破译这个执行计划以在查询中找到优化它的方法,我将永远感激不尽。我还有更多的查询需要优化——我只需要一个跳板来帮助我完成第一个查询。

这是查询:

DECLARE @Param0 DATETIME     = '2013-07-29';
DECLARE @Param1 INT          = CONVERT(INT, CONVERT(VARCHAR, @Param0, 112))
DECLARE @Param2 VARCHAR(50)  = 'ABC';
DECLARE @Param3 VARCHAR(100) = 'DEF';
DECLARE @Param4 VARCHAR(50)  = 'XYZ';
DECLARE @Param5 VARCHAR(100) = NULL;
DECLARE @Param6 VARCHAR(50)  = 'Text3';

SET NOCOUNT ON

DECLARE @MyTableVar TABLE
(
    B_Var1_PK int,
    Job_Var1 varchar(512),
    Job_Var2 varchar(50)
)

INSERT INTO @MyTableVar (B_Var1_PK, Job_Var1, Job_Var2) 
SELECT B_Var1_PK, Job_Var1, Job_Var2 FROM [fn_GetJobs] (@Param1, @Param2, @Param3, @Param4, …
Run Code Online (Sandbox Code Playgroud)

sql-server-2008 sql-server optimization t-sql execution-plan

16
推荐指数
1
解决办法
2万
查看次数

如何在维护计划作业中更改或更新本地服务器连接

两天前,我们的客户更改了我们的开发服务器名称之一

服务器重命名后,由于服务器名称不匹配,我所有的维护工作和其他工作都失败了。

我们使用的是sql server 2012版本和server 2008 操作系统

所以今天早上我将我的 Sql server 2012 名称重命名为更新的给定名称并制作表,程序更新

我试图在维护工作中更新本地服务器连接,但它是不可编辑的。然后我添加了新的服务器连接,但仍然没有用我在执行作业时遇到错误。

在我尝试在作业属性选项中使用目标页面后,也只选择了目标服务器并禁用了多个目标服务器。

下面的错误

以用户身份执行:NT Service\SQLSERVERAGENT。Microsoft (R) SQL Server 执行包实用程序版本 11.0.2100.60,适用于 64 位 版权所有 (C) Microsoft Corporation。版权所有。
开始时间:12:01:28 AM 错误:2013-12-16 00:01:43.98 代码:0xC00291EC 来源:{410F7661-F71A-4B68-9584-BA422AB00F02} 执行 SQL
连接任务说明:获取本地服务器连接失败. 连接可能未正确配置,或者您可能没有此连接的正确权限。结束错误
错误:2013-12-16 00:02:00.00
代码:0xC0024104
来源:Territory_Update
说明:任务上的 Execute 方法返回错误代码 0x80131904(建立与 SQL Server 的连接时发生与网络相关或特定于实例的错误。未找到或无法访问服务器。验证实例名称是否正确,并且SQL Server 配置为允许远程连接。(提供程序:命名管道提供程序,错误:40 - 无法打开与 SQL Server 的连接))。Execute 方法必须成功,并使用“out”参数指示结果。结束错误
错误:2013-12-16 00:02:15.00
代码:0xC0024104
来源:{4E2AF328-0B8D-4905-83BE-839FDDEFC09C}
说明:任务上的 Execute 方法返回错误代码 0x80131904(建立与 SQL Server 的连接时发生与网络相关或特定于实例的错误。找不到服务器或无法访问服务器。验证实例名称是否正确,并且SQL Server 配置为允许远程连接。(提供程序:命名管道提供程序,错误:40 - 无法打开与 SQL Server 的连接))。Execute 方法必须成功,并使用“out”参数指示结果。
结束错误 …

maintenance t-sql sql-server-2012 jobs

16
推荐指数
2
解决办法
3万
查看次数

随机数和连接类型的意外结果

我有一个简单的脚本,它获取四个随机数(1 到 4),然后重新连接以获取匹配的 database_id 数。当我使用 LEFT JOIN 运行脚本时,我每次都返回四行(预期结果)。但是,当我使用 INNER JOIN 运行它时,会得到不同数量的行——有时是两行,有时是八行。

从逻辑上讲,应该没有任何区别,因为我知道 sys.databases 中存在 database_ids 1-4 的行。因为我们是从四行的随机数表中选择的(而不是加入它),所以返回的行不应该超过四行。

这在 SQL Server 2012 和 2014 中都会发生。是什么导致 INNER JOIN 返回不同数量的行?

/* Works as expected -- always four rows */

SELECT rando.RandomNumber, d.database_id
FROM 
  (SELECT 1 + ABS(CHECKSUM(NEWID())) % (4) AS RandomNumber 
   FROM sys.databases WHERE database_id <= 4) AS rando
LEFT JOIN sys.databases d ON rando.RandomNumber = d.database_id;


/* Returns a varying number of rows */

SELECT rando.RandomNumber, d.database_id
FROM 
  (SELECT 1 + ABS(CHECKSUM(NEWID())) …
Run Code Online (Sandbox Code Playgroud)

sql-server t-sql

16
推荐指数
2
解决办法
920
查看次数

当我添加连接提示时,为什么 SQL Server 行估计会发生变化?

我有一个查询,它连接了几个表并且执行得非常糟糕 - 行估计偏离了(1000 次)并且选择了嵌套循环连接,从而导致多个表扫描。查询的形状相当简单,看起来像这样:

SELECT t1.id
FROM t1
INNER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
LEFT OUTER JOIN t4 ON t3.t4_id = t4.id 
WHERE t4.id = some_GUID
Run Code Online (Sandbox Code Playgroud)

玩弄查询时,我注意到当我提示它对其中一个连接使用合并连接时,它的运行速度要快很多倍。这我可以理解 - 合并连接是连接数据的更好选择,但 SQL Server 只是没有正确选择嵌套循环。

我不完全理解的是为什么这个连接提示会改变所有计划运营商的所有估计?通过阅读不同的文章和书籍,我假设基数估计是在构建计划之前执行的,因此使用提示不会改变估计,而是明确告诉 SQL Server 使用特定的物理连接实现。

然而,我看到的是合并提示使所有估计变得非常完美。为什么会发生这种情况,是否有任何通用技术可以使查询优化器在没有提示的情况下做出更好的估计 - 考虑到统计数据显然允许这样做?

UPD:匿名执行计划可以在这里找到:https ://www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan?dl =0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl =0

我使用 TF 3604、9292 和 9204 检查了这两个查询使用的统计数据,它们是相同的。然而,被扫描/搜索的索引在查询之间是不同的。

除此之外,我尝试运行查询OPTION (FORCE ORDER)- 它比使用合并联接运行得更快,为每个联接选择 HASH MATCH。

performance sql-server optimization t-sql performance-tuning

16
推荐指数
1
解决办法
584
查看次数

创建多个级别的层次结构,其中每个节点都有随机数量的子节点

我需要创建一些涉及层次结构的测试数据。我可以让它变得简单并做几个CROSS JOINs,但这会给我一个完全统一/没有任何变化的结构。这不仅看起来很乏味,而且测试数据缺乏变化有时会掩盖原本会发现的问题。所以,我想生成一个遵循以下规则的非统一层次结构:

  • 3 层深
    • 1 级随机 5 - 20 个节点
    • 级别 2 是 1 - 10 个节点,每个级别 1 的每个节点随机
    • 级别 3 是 1 - 5 个节点,每个级别 2 的每个节点随机
  • 所有分支都将有 3 层深。在这一点上,深度的均匀性是可以的。
  • 任何给定级别上的子节点的名称都可以重叠(即子节点的名称在同一级别的所有节点中不需要是唯一的)。
  • 术语“随机”在这里定义为伪随机,而不是唯一随机。这需要提及,因为术语“随机”通常用于表示“不产生重复的给定集合的随机排序”。我接受 random = random 并且如果级别 1 的每个节点的子节点数仅为 4、7 和 8,即使级别 1 上的 20 个节点每个节点的潜在分布为 1 - 10 个子节点,那很好,因为这就是随机。
  • 尽管使用嵌套WHILE循环可以很容易地做到这一点,但首选是找到一种基于集合的方法。一般而言,生成测试数据没有生产代码对效率的要求,但尝试基于集合的方法可能会更具教育意义,并有助于在未来找到基于集合的方法来解决问题。因此WHILE,不排除循环,但只有在不可能使用基于集合的方法时才能使用循环。
  • Set-based = 理想情况下是单个查询,无论 CTE、APPLY 等如何。因此使用现有或内联数字表很好。使用 WHILE / CURSOR / 程序方法是行不通的。我想将部分数据暂存到临时表或表变量中就可以了,只要操作都是基于集合的,没有循环。然而,话虽如此,单查询方法可能比多查询更受青睐,除非可以证明多查询方法实际上更好。另请记住,“更好”的构成通常是主观的;-)。还请记住,前一句中“典型地”的用法也是主观的。
  • 任何版本的 SQL Server(我想是 2005 和更新版本)都可以。
  • 只有纯 T-SQL:没有那些愚蠢的 SQLCLR 东西!!至少在生成数据方面。将使用 SQLCLR 创建目录和文件。但在这里,我只是专注于产生要创造的价值。 …

sql-server hierarchy random t-sql

16
推荐指数
2
解决办法
1万
查看次数

将存储过程的结果插入到表变量中

我有一个将值存储在表变量中的存储过程。我选择这些值并在调用过程时返回它们。

我试图在另一个表变量中设置这些返回值,但我无法弄清楚。

存储过程

ALTER PROCEDURE [dbo].[GetOrSetDomainId]
@DomainName varchar(50),
@DomainUrl varchar(50)
AS
BEGIN
    DECLARE @DomainId bigint;
    DECLARE @NumberOfRwos bigint;

    DECLARE @DomainHistory TABLE
    (
        DomainId bigint, 
        HasHistory bit,
        ServerOnline bit,
        DatabaseOnline bit, 
        ServerPerformance bigint,
        DatabasePerformance bigint, 
        SoldTickets bigint
    )


    SELECT  @NumberOfRwos =  COUNT(Id) 
    FROM DomainData
    WHERE DomainName = @DomainName OR DomainUrl = @DomainUrl

    IF(@NumberOfRwos = 0)
    BEGIN
        INSERT INTO DomainData (DomainName, DomainUrl) VALUES (@DomainName, @DomainUrl)

         SELECT @DomainId =  @@IDENTITY

         INSERT INTO @DomainHistory(DomainId,HasHistory)VALUES(@DomainId, 0)

         SELECT * FROM @DomainHistory
    END

    ELSE
    BEGIN
    ---not important …
Run Code Online (Sandbox Code Playgroud)

sql-server stored-procedures t-sql temporary-tables

16
推荐指数
1
解决办法
6万
查看次数