我知道之前已经问过同样的问题,但情况略有不同,我想更多地解释为什么它在我的上下文中失败,当(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) 我在理解为什么此代码在组表 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)
我的数据库中有一个表,其中存储了成功和失败的登录尝试。我正在创建一个存储过程,允许我们删除超过 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) 考虑以下 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 中的类型中返回具有最高优先级的数据类型”。
我正在使用 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声明,结果变得最糟。
我得出的结论是,sp在TRY_CATCH块内创建是不切实际的。
这甚至可以sp在TRY_CATCH块内创建吗?如何?
我一直在到处搜索,但我找不到任何关于它的东西,似乎每个人都只关心 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 会有什么不同吗?
我有几个字符被替换为?. 你如何保持表格中的原始字符?我要插入的字符是?; 带腰带的拉丁文小写字母 L。是否可以将此字符添加到表中?
我一直在尝试编写一个函数来检查一个字符串是否包含一个数字,而该数字不是更大数字的一部分(换句话说,如果要搜索的数字是 '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) 我有一个简单的一级父子关系表,包含以下列:
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) 我需要帮助选择日期在前 3 个月内的数据。(注意:我不是要求过去 3 个月即DATEADD(MONTH, -3, GETDATE()))
我不想使用 DATEADD 方法的原因是这个查询可以在月中运行,我不希望它返回到那个点之前的数据