SQL存储过程仅返回函数创建的表的第一行

标签 sql sql-server

我有一个函数,可以将分隔的 VARCHAR 转换为 INT 表。

内部分割:

USE [master]
GO

/****** Object:  UserDefinedFunction [dbo].[IntSplit]    Script Date: 02/10/2016 15:17:06 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[IntSplit]
(
    @String NVARCHAR(4000),
    @Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
    WITH Split(stpos,endpos)
    AS(
        SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
        UNION ALL
        SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
            FROM Split
            WHERE endpos > 0
    )
    SELECT 'Data' = CONVERT(INT, SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos))
    FROM Split
)

GO

当我在查询中运行此命令时:

SELECT * FROM IntSplit('1,2,3', ',')

我得到了预期的结果:

 |Data
-+----
1| 1
2| 2
3| 3

我还有一个存储过程,它执行完全相同的操作(即调用函数)

my_int_split:

USE [master]
GO

/****** Object:  StoredProcedure [dbo].[my_int_split]    Script Date: 02/10/2016 15:29:16 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[my_int_split]
(@i_ids VARCHAR)
AS
    -- Common set conditions
    -- Explicity suppress count information
    SET NOCOUNT ON
    -- Unhandled exception aborts whole transaction
    SET XACT_ABORT ON
    -- Autocommit on
    SET IMPLICIT_TRANSACTIONS OFF
    -- UK datetime
    SET DATEFORMAT dmy
    --
    SET NOCOUNT ON
    --
    BEGIN
        SELECT * FROM IntSplit(@i_ids, ',')
    END

GO

但是,如果我运行存储过程

my_int_split '1,2,3'

然后我只得到第一行作为结果

 |Data
-+----
1| 1

据我所知,存储过程正在执行与查询完全相同的操作,但只返回顶行。请注意,如果我输入 '2,3,4' 的 VARCHAR,它将返回单行值 2,因此它并不总是吐出 1。

有什么想法吗?

最佳答案

切勿使用没有长度的 VARCHAR,您的 @i_ids 参数将被截断为 1 个字符。

如果您知道 ID 列表可能会变得多长,请以此为指导来指定最大长度(加上一些余量);否则使用 VARCHAR(MAX) ,效率较低,但大小几乎任意。

此外,请避免混合使用 NVARCHAR(在函数中)和 VARCHAR(在 SP 中) - 这样做可能会因转换而导致性能下降。此外(虽然在这种特定情况下不适用),它可能会导致索引被跳过,因为数据类型不相同。

“有趣”的是,没有给出长度时假定的长度不一致。请参阅Aaron Bertrand's blog post了解更多详细信息。

关于SQL存储过程仅返回函数创建的表的第一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35320088/

相关文章:

php - 从同一表的两个不同列中选择不同的值

sql - 修改现有触发器的程序

c# - 如何让 SqlBulkCopy 告诉我哪个列有截断错误

php - SQL/PHP : How to upload big database to server when I have import file size limit? 然后更新

c# - 如何将数组作为 Cosmos DB 查询的 SQL 查询参数传递

mysql - GROUP BY 到 JOIN 转换的 ORDER BY 子查询

java - sql 或 sqlite 查询并在列表中获取结果

sql - 是什么使这些查询之一更快?

sql-server - 如何在 SSIS 中插入新记录之前清空目标表?

sql - 在记录集中没有出现的字段上选择 DISTINCT?