标签: t-sql

无法对“FunctionName”执行更改,因为它是不兼容的对象类型

我知道之前已经问过同样的问题,但情况略有不同,我想更多地解释为什么它在我的上下文中失败,当(AFAIK)返回类型相同时。

过去,在我的数据库中,我使用基于 CLR 的表值函数将逗号分隔值拆分为包含整数列的表。

因为 SQL2016 引入了STRING_SPLIT,我需要换掉这个函数的 CLR 部分,并替换为原生的 TSQL 函数(因为我有数百个依赖这个函数的存储过程)。

如果我在 SSMS 中修改这个函数,我会看到:

ALTER FUNCTION [dbo].[e4fn_CreateIdTable](
     @Ids [nvarchar](max), 
     @separator [nchar](1))
RETURNS TABLE (
    [IdVal] [int] NULL
) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [ValueSplitter].[MyCompany.ValueSplitter].[SplitToIntegers]
Run Code Online (Sandbox Code Playgroud)

我希望我能够像这样改变它:

ALTER FUNCTION [dbo].[e4fn_CreateIdTable] (
    @Ids [nvarchar](max), 
    @separator [nchar](1)
)
RETURNS TABLE 
AS RETURN
(
    SELECT
        CAST(NULLIF(LTRIM(RTRIM(value)), '') AS int) AS IdVal
    FROM
        STRING_SPLIT(@Ids, @separator)
)
GO
Run Code Online (Sandbox Code Playgroud)

这返回了错误:

无法对“dbo.e4fn_CreateIdTable”执行更改,因为它是不兼容的对象类型。

我认为这是因为没有明确定义输出参数的表定义。所以,我这样重试:

ALTER FUNCTION [dbo].[e4fn_CreateIdTable] (
    @Ids [nvarchar](max), 
    @separator [nchar](1)
)
RETURNS …
Run Code Online (Sandbox Code Playgroud)

sql-server t-sql sql-server-2016

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

加盟业绩

我在理解为什么此代码在组表 400000 行中返回数百万行时遇到了一些问题。RID 循环和 t2 上的索引查找应返回 1 行,它们返回组表中的所有行。

Create table #group (IDperson uniqueidentifier, MGroup_Idx int, 
NGroup_Idx int)
create index i1 on #group (NGroup_Idx); 

-- insert some data 

SELECT * FROM #group t 
LEFT JOIN #group t2  ON t.NGroup_Idx = t2.NGroup_Idx 
AND t2.MGroup_Idx IS not NULL
WHERE ISNULL(t.MGroup_Idx, t2.MGroup_Idx) IS NOT NULL
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

在此处输入图片说明

sql-server t-sql sql-server-2012

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

基于参数值的带有“AND”的 case 语句的存储过程

我的数据库中有一个表,其中存储了成功和失败的登录尝试。我正在创建一个存储过程,允许我们删除超过 X 天的记录。到目前为止一切顺利,但我想把它提高一个(或两个)等级,并允许我们指定是否删除关于 [Success] 列是真、假还是两者兼而有之的记录。不过,我在连接需要执行的脚本时遇到了一些问题。

这是我到目前为止所做的:

-- CREATE PROCEDURE [dbo].[sp_delete_log_attempts]
DECLARE @backDays INT = 1 -- Default to 30 days (one test finishes)
DECLARE @successArg BIT = NULL -- default to both true and false success logins
DECLARE @successAnd VARCHAR(50)
DECLARE @query VARCHAR(MAX)

SET @successAnd = CASE
WHEN @successArg = 'true' THEN
    'AND [Success] = ''true'''
WHEN @successArg = 'false' THEN
    'AND [Success] = ''false'''
ELSE
    'AND [Success] = ''true'' OR [Success] = ''false'''
END

PRINT @successAnd -- just for …
Run Code Online (Sandbox Code Playgroud)

stored-procedures dynamic-sql t-sql

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

为什么 case/iif 返回可为空的数据类型?

考虑以下 sproc:

create or alter procedure TestSproc
as
begin

declare @ZeroBit bit = 0, @OneBit bit = 1

-- Table.Id is a nullable integer column
select iif(Table.Id is null, @ZeroBit, @OneBit) as ColumnNotNull

end
Run Code Online (Sandbox Code Playgroud)

编译完成后,运行以下命令:

select name, system_type_name, is_nullable
  from sys.dm_exec_describe_first_result_set_for_object(object_id('TestSproc'), 0)
Run Code Online (Sandbox Code Playgroud)

显示ColumnNotNull正确键入为 a的列bit但它可以为 null

可空性对我来说没有意义,因为我传递给的参数iif是非空常量,那么为什么结果列可以为空?是否有可能让它不可为空而不用包装表达式isnull来解决这个问题,在我看来这是 - 或者更确切地说,应该是 - 不必要的?

的文档iif没有提到可空性,只是说明此函数“从 true_value 和 false_value 中的类型中返回具有最高优先级的数据类型”。

sql-server t-sql

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

在 try-catch 块中创建存储过程

我正在使用 sqlserver 2014 并尝试创建一个StoredProcedure像这样的内部 try-catch 块:

BEGIN TRY   
  CREATE PROCEDURE [ammeghezi1] (@w INT) AS SELECT '' 
END TRY
BEGIN CATCH
  ...
END CATCH
Run Code Online (Sandbox Code Playgroud)

它无法运行并出现以下错误:Incorrect syntax near 'SELECT' Expecting EXTERNAL.
然后我更改了 sp 如下:(CREATE PROCEDURE [ammeghezi1] (@w INT) AS BEGIN SELECT '' END用 BEGIN-END 块覆盖 sp),但错误没有改变。我还添加了GOafterBEGIN TRY声明,结果变得最糟。
我得出的结论是,spTRY_CATCH块内创建是不切实际的。

这甚至可以spTRY_CATCH块内创建吗?如何?

sql-server t-sql ddl

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

JOIN 短路

我一直在到处搜索,但我找不到任何关于它的东西,似乎每个人都只关心 WHERE 和 CASE。(而且我手头没有 SQL Server 来亲自验证它)

那么,一个简单的问题:SQL Server 是否基于 JOIN 条件短路 JOIN?如果我写:

TableA LEFT OUTER JOIN TableB ON 1=0 AND TableA.ID = TableB.A_ID
Run Code Online (Sandbox Code Playgroud)

SQL Server 会跳过连接吗?


编辑

好的,有人正确地指出这是在编译时解决的,所以我最好扩展一下这个问题。

以上只是作为一个例子,但结果证明这是一个糟糕的例子。我想知道的是,当这种情况在运行时发生时,SQL Server 是否会短路 JOIN,作为传递给存储过程的 @parameter 的结果。

我问是因为我肯定在过去几年中使用过类似的东西,但我想在与一些同事谈论它之前 100% 确定。那么,SQL Server 是否会将其短路,然后:

TableA LEFT OUTER JOIN TableB ON @parameter IS NOT NULL AND TableA.ID = TableB.A_ID
Run Code Online (Sandbox Code Playgroud)

如果它在 SP 内并且在 @parameter 设置为 NULL 的情况下调用它?如果存储过程是 WITH RECOMPILE 会有什么不同吗?

join sql-server t-sql

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

在表格中插入特殊字符

我有几个字符被替换为?. 你如何保持表格中的原始字符?我要插入的字符是?; 带腰带的拉丁文小写字母 L。是否可以将此字符添加到表中?

sql-server collation insert t-sql unicode

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

试图检查一个字符串是否只包含一个数字

我一直在尝试编写一个函数来检查一个字符串是否包含一个数字,而该数字不是更大数字的一部分(换句话说,如果要搜索的数字是 '6' 而字符串是 '7+16+2'它应该返回 false,因为这个字符串中的 '6' 是数字 '16' 的一部分)

我写了下面的函数(它很长,但我打算在重构之前先测试它)

在测试时,我发现了一个错误,它仅通过逻辑运行找到的数字的第一个实例。因此,使用 '6' 对 '16+7+9+6' 运行此函数将返回 false,因为它确定第一个 '6' 是更大数字的一部分并停止处理。

我认为要解决这个问题,我必须实现一个循环来缩短 'haystack' 字符串(这样,使用示例 '16+7+9+6',该函数在消除后继续检查 '+7+9+6'第一个“6”)但在花时间使已经复杂的函数变得更加复杂之前,我想检查是否有更简单的方法来实现相同的目标?

drop function dbo.runners_contain_runner
go
create function dbo.runners_contain_runner(@runner varchar(max), @runners varchar(max))
returns int
as 
begin

    /*
    eliminate the plus sign from @runners so that the 
    'isnumeric' function doesn't return false positives (it returns 1 for '+') 
    */
    set @runners = replace(@runners,'+','_' ) 


    declare @ret int;
    set @ret = 0;

    -- if the runner is the only runner return …
Run Code Online (Sandbox Code Playgroud)

sql-server-2005 sql-server t-sql pattern-matching substring

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

使用 SORT 选择父子

我有一个简单的一级父子关系表,包含以下列:

ID_Asset| Parent_ID_Asset | ProductTitle
Run Code Online (Sandbox Code Playgroud)

我需要按父级后跟子级分组的输出,并按父级和子级名称排序。我在小提琴中的尝试。父母必须是第一位的。

详情请看这里:https : //rextester.com/PPCHG20007

CREATE TABLE [dbo].[Test](
    [ID_Asset] [int] NOT NULL,
    [Parent_ID_Asset] [int] NULL,
    [ProductTitle] [nvarchar](150) NOT NULL
) ON [PRIMARY]
GO

INSERT [dbo].[Test] ([ID_Asset], [Parent_ID_Asset], [ProductTitle]) VALUES (2, NULL, N'Live Maps Unity')
INSERT [dbo].[Test] ([ID_Asset], [Parent_ID_Asset], [ProductTitle]) VALUES (3, NULL, N'mShare')
INSERT [dbo].[Test] ([ID_Asset], [Parent_ID_Asset], [ProductTitle]) VALUES (4, NULL, N'Nessus Professional')
INSERT [dbo].[Test] ([ID_Asset], [Parent_ID_Asset], [ProductTitle]) VALUES (5, NULL, N'Enterprise Server')
INSERT [dbo].[Test] ([ID_Asset], [Parent_ID_Asset], [ProductTitle]) VALUES (6, NULL, N'PhantomPDF')
INSERT …
Run Code Online (Sandbox Code Playgroud)

sql-server order-by t-sql select

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

选择前 3 个月的数据

我需要帮助选择日期在前 3 个月内的数据。(注意:我不是要求过去 3 个月即DATEADD(MONTH, -3, GETDATE())

我不想使用 DATEADD 方法的原因是这个查询可以在月中运行,我不希望它返回到那个点之前的数据

sql-server t-sql date

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