将表作为参数传递到sql server UDF中

时间:2021-08-22 08:38:19

I'd like to pass a table as a parameter into a scaler UDF.

我想将一个表作为参数传递给标量UDF。

I'd also prefer to restrict the parameter to tables with only one column. (optional)

我还希望将参数限制为只有一个列的表。(可选)

Is this possible?

这是可能的吗?

EDIT

编辑

I don't want to pass a table name, I'd like to pass the table of data (as a reference I presume)

我不想传递表名,我想传递数据表(作为引用)

EDIT

编辑

I would want my Scaler UDF to basically take a table of values and return a CSV list of the rows.

我希望我的Scaler UDF获取一个值表并返回一个列的CSV列表。

IE

col1  
"My First Value"  
"My Second Value"
...
"My nth Value"

would return

将返回

"My First Value, My Second Value,... My nth Value"

I'd like to do some filtering on the table though, IE ensuring that there are no nulls and to ensure there are no duplicates. I was expecting something along the lines of:

我想对表做一些过滤(确保没有空值,确保没有重复的值)。我正期待着一些类似的事情:

SELECT dbo.MyFunction(SELECT DISTINCT myDate FROM myTable WHERE myDate IS NOT NULL)

10 个解决方案

#1


14  

Unfortunately, there is no simple way in SQL Server 2005. Lukasz' answer is correct for SQL Server 2008 though and the feature is long overdue

不幸的是,在SQL Server 2005中没有简单的方法。Lukasz的回答对于SQL Server 2008来说是正确的,这个功能早就应该出现了

Any solution would involve temp tables, or passing in xml/CSV and parsing in the UDF. Example: change to xml, parse in udf

任何解决方案都会涉及临时表,或者在UDF中传递xml/CSV和解析。示例:更改为xml,在udf中解析

DECLARE @psuedotable xml

SELECT
    @psuedotable = ...
FROM
    ...
FOR XML ...

SELECT ... dbo.MyUDF (@psuedotable)

What do you want to do in the bigger picture though? There may be another way to do this...

但是,从更大的角度来看,你想做什么?也许还有别的方法可以做到这一点……

Edit: Why not pass in the query as a string and use a stored proc with output parameter

编辑:为什么不将查询作为字符串传入,并使用带有输出参数的存储proc

Note: this is an untested bit of code, and you'd need to think about SQL injection etc. However, it also satisfies your "one column" requirement and should help you along

注意:这是一段未经测试的代码,您需要考虑SQL注入等。但是,它也满足您的“一列”需求,应该对您有所帮助

CREATE PROC dbo.ToCSV (
    @MyQuery varchar(2000),
    @CSVOut varchar(max)
)
AS
SET NOCOUNT ON

CREATE TABLE #foo (bar varchar(max))

INSERT #foo
EXEC (@MyQuery)

SELECT
    @CSVOut = SUBSTRING(buzz, 2, 2000000000)
FROM
    (
    SELECT 
        bar -- maybe CAST(bar AS varchar(max))??
    FROM 
        #foo
    FOR XML PATH (',')
    ) fizz(buzz)
GO

#2


62  

You can, however no any table. From documentation:

你可以,但是没有任何桌子。从文档:

For Transact-SQL functions, all data types, including CLR user-defined types and user-defined table types, are allowed except the timestamp data type.

对于Transact-SQL函数,除了时间戳数据类型之外,所有数据类型(包括CLR用户定义类型和用户定义表类型)都是允许的。

You can use user-defined table types.

您可以使用用户定义的表类型。

Example of user-defined table type:

用户定义的表类型示例:

CREATE TYPE TableType 
AS TABLE (LocationName VARCHAR(50))
GO 

DECLARE @myTable TableType
INSERT INTO @myTable(LocationName) VALUES('aaa')
SELECT * FROM @myTable

So what you can do is to define your table type, for example TableType and define funcion which takes the parameter of this type.An example function:

所以你能做的就是定义你的表类型,例如表类型和定义函数它取这个类型的参数。功能:一个例子

CREATE FUNCTION Example( @TableName TableType READONLY)
RETURNS VARCHAR(50)
AS
BEGIN
    DECLARE @name VARCHAR(50)

    SELECT TOP 1 @name = LocationName FROM @TableName
    RETURN @name
END

The parameter has to be READONLY. And example usage:

参数必须是只读的。和示例用法:

DECLARE @myTable TableType
INSERT INTO @myTable(LocationName) VALUES('aaa')
SELECT * FROM @myTable

SELECT dbo.Example(@myTable)

Depending of what you want achieve you can modify this code.

根据您想要实现的目标,您可以修改此代码。

EDIT: If you have a data in a table you may create a variable:

编辑:如果表中有数据,可以创建一个变量:

DECLARE @myTable TableType

And take data from your table to the variable

从表中取数据到变量中

INSERT INTO @myTable(field_name)
SELECT field_name_2 FROm my_other_table

#3


2  

Cutting to the bottom line, you want a query like SELECT x FROM y to be passed into a function that returns the values as a comma separated string.

对于底线,您需要一个查询,比如从y中选择x,将其传递给一个函数,该函数返回值作为逗号分隔的字符串。

As has already been explained you can do this by creating a table type and passing a UDT into the function, but this needs a multi-line statement.

正如已经解释的那样,您可以通过创建一个表类型并将UDT传递到函数来实现这一点,但是这需要一个多行语句。

You can pass XML around without declaring a typed table, but this seems to need a xml variable which is still a multi-line statement i.e.

您可以在不声明类型化表的情况下传递XML,但是这似乎需要一个XML变量,它仍然是一个多行语句。

DECLARE @MyXML XML = (SELECT x FROM y FOR XML RAW);
SELECT Dbo.CreateCSV(@MyXml);

The "FOR XML RAW" makes the SQL give you it's result set as some xml.

“FOR XML RAW”使SQL将其结果设置为一些XML。

But you can bypass the variable using Cast(... AS XML). Then it's just a matter of some XQuery and a little concatenation trick:

但是可以使用Cast来绕过变量(……)作为XML)。然后就是一些XQuery和一些连接技巧:

CREATE FUNCTION CreateCSV (@MyXML XML) 
RETURNS VARCHAR(MAX)
BEGIN
    DECLARE @listStr VARCHAR(MAX);
    SELECT 
            @listStr = 
                COALESCE(@listStr+',' ,'') + 
                c.value('@Value[1]','nvarchar(max)') 
        FROM @myxml.nodes('/row') as T(c)
    RETURN @listStr
END
GO

-- And you call it like this:
SELECT Dbo.CreateCSV(CAST((    SELECT x FROM y    FOR XML RAW) AS XML));

-- Or a working example
SELECT Dbo.CreateCSV(CAST((
        SELECT DISTINCT number AS Value 
        FROM master..spt_values 
        WHERE type = 'P' 
            AND number <= 20
    FOR XML RAW) AS XML));

As long as you use FOR XML RAW all you need do is alias the column you want as Value, as this is hard coded in the function.

只要您对XML RAW使用,您所需要做的就是将您想要的列别名为Value,因为这是函数中的硬编码。

#4


2  

Step 1: Create a Type as Table with name TableType that will accept a table having one varchar column

步骤1:创建一个名为TableType的表,它将接受一个具有一个varchar列的表。

create type TableType
as table ([value] varchar(100) null)

Step 2: Create a function that will accept above declared TableType as Table-Valued Parameter and String Value as Separator

步骤2:创建一个函数,该函数将接受上面声明的表类型作为表值参数,字符串值作为分隔符

create function dbo.fn_get_string_with_delimeter (@table TableType readonly,@Separator varchar(5))
returns varchar(500)
As
begin

    declare @return varchar(500)

    set @return = stuff((select @Separator + value from @table for xml path('')),1,1,'')

    return @return

end

Step 3: Pass table with one varchar column to the user-defined type TableType and ',' as separator in the function

步骤3:将一个varchar列的表传递给用户定义的类型表类型和',',作为函数中的分隔符

select dbo.fn_get_string_with_delimeter(@tab, ',')

#5


1  

I've been dealing with a very similar problem and have been able to achieve what I was looking for, even though I'm using SQL Server 2000. I know it is an old question, but think its valid to post here the solution since there should be others like me that use old versions and still need help.

我一直在处理一个非常相似的问题,并且能够实现我所期望的,即使我正在使用SQL Server 2000。我知道这是一个老问题,但我认为在这里发布解决方案是有效的,因为应该有像我这样的人使用旧版本,仍然需要帮助。

Here's the trick: SQL Server won't accept passing a table to a UDF, nor you can pass a T-SQL query so the function creates a temp table or even calls a stored procedure to do that. So, instead, I've created a reserved table, which I called xtList. This will hold the list of values (1 column, as needed) to work with.

这里有一个诀窍:SQL Server不接受将表传递给UDF,也不能传递T-SQL查询,因此该函数创建一个临时表,甚至调用一个存储过程来实现这一点。因此,我创建了一个保留表,我将其命名为xtList。这将包含用于处理的值列表(需要的1列)。

CREATE TABLE [dbo].[xtList](
    [List] [varchar](1000) NULL
) ON [PRIMARY]

Then, a stored procedure to populate the list. This is not strictly necessary, but I think is very usefull and best practice.

然后,填充列表的存储过程。这不是绝对必要的,但我认为这是非常有用的和最好的实践。

-- =============================================
-- Author:      Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE PROCEDURE [dbo].[xpCreateList]
    @ListQuery varchar(2000)
AS
BEGIN
    SET NOCOUNT ON;

  DELETE FROM xtList

  INSERT INTO xtList
    EXEC(@ListQuery)
END

Now, just deal with the list in any way you want, using the xtList. You can use in a procedure (for executing several T-SQL commands), scalar functions (for retrieving several strings) or multi-statement table-valued functions (retrieves the strings but like it was inside a table, 1 string per row). For any of that, you'll need cursors:

现在,用你想要的任何方式来处理列表,使用并置列表。您可以在过程(用于执行多个T-SQL命令)、标量函数(用于检索多个字符串)或多语句表值函数(检索字符串,但像在表中一样,每行一个字符串)中使用。其中任何一种都需要游标:

DECLARE @Item varchar(100)
DECLARE cList CURSOR DYNAMIC
  FOR (SELECT * FROM xtList WHERE List is not NULL)
  OPEN cList

FETCH FIRST FROM cList INTO @Item
WHILE @@FETCH_STATUS = 0 BEGIN

  << desired action with values >>

FETCH NEXT FROM cList INTO @Item
END
CLOSE cList
DEALLOCATE cList

The desired action would be as follows, depending on which type of object created:

所需的行动将如下,视所创建对象的类型而定:

Stored procedures

存储过程

-- =============================================
-- Author:      Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE PROCEDURE [dbo].[xpProcreateExec]
(
    @Cmd varchar(8000),
    @ReplaceWith varchar(1000)
)
AS
BEGIN
  DECLARE @Query varchar(8000)

  << cursor start >>
    SET @Query = REPLACE(@Cmd,@ReplaceWith,@Item)
    EXEC(@Query)
  << cursor end >>
END

/* EXAMPLES

  (List A,B,C)

  Query = 'SELECT x FROM table'
    with EXEC xpProcreateExec(Query,'x') turns into
  SELECT A FROM table
  SELECT B FROM table
  SELECT C FROM table

  Cmd = 'EXEC procedure ''arg''' --whatchout for wrong quotes, since it executes as dynamic SQL
    with EXEC xpProcreateExec(Cmd,'arg') turns into
  EXEC procedure 'A'
  EXEC procedure 'B'
  EXEC procedure 'C'

*/

Scalar functions

标量函数

-- =============================================
-- Author:      Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE FUNCTION [dbo].[xfProcreateStr]
(
    @OriginalText varchar(8000),
    @ReplaceWith varchar(1000)
)
RETURNS varchar(8000)
AS
BEGIN
    DECLARE @Result varchar(8000)

  SET @Result = ''
  << cursor start >>
    SET @Result = @Result + REPLACE(@OriginalText,@ReplaceWith,@Item) + char(13) + char(10)
  << cursor end >>

    RETURN @Result
END

/* EXAMPLE

  (List A,B,C)

  Text = 'Access provided for user x'
    with "SELECT dbo.xfProcreateStr(Text,'x')" turns into
  'Access provided for user A
  Access provided for user B
  Access provided for user C'

*/

Multi-statement table-valued functions

Multi-statement表值函数

-- =============================================
-- Author:      Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE FUNCTION [dbo].[xfProcreateInRows]
(
    @OriginalText varchar(8000),
    @ReplaceWith varchar(1000)
)
RETURNS 
@Texts TABLE 
(
    Text varchar(2000)
)
AS
BEGIN
  << cursor start >>
      INSERT INTO @Texts VALUES(REPLACE(@OriginalText,@ReplaceWith,@Item))
  << cursor end >>
END

/* EXAMPLE

  (List A,B,C)

  Text = 'Access provided for user x'
    with "SELECT * FROM dbo.xfProcreateInRow(Text,'x')" returns rows
  'Access provided for user A'
  'Access provided for user B'
  'Access provided for user C'

*/

#6


0  

To obtain the column count on a table, use this:

要获取表上的列计数,请使用以下方法:

select count(id) from syscolumns where id = object_id('tablename')

and to pass a table to a function, try XML as show here:

要将表传递给函数,请尝试如下所示的XML:

create function dbo.ReadXml (@xmlMatrix xml)
returns table
as
return
( select
t.value('./@Salary', 'integer') as Salary,
t.value('./@Age', 'integer') as Age
from @xmlMatrix.nodes('//row') x(t)
)
go

declare @source table
( Salary integer,
age tinyint
)
insert into @source
select 10000, 25 union all
select 15000, 27 union all
select 12000, 18 union all
select 15000, 36 union all
select 16000, 57 union all
select 17000, 44 union all
select 18000, 32 union all
select 19000, 56 union all
select 25000, 34 union all
select 7500, 29
--select * from @source

declare @functionArgument xml

select @functionArgument =
( select
Salary as [row/@Salary],
Age as [row/@Age]
from @source
for xml path('')
)
--select @functionArgument as [@functionArgument]

select * from readXml(@functionArgument)

/* -------- Sample Output: --------
Salary Age
----------- -----------
10000 25
15000 27
12000 18
15000 36
16000 57
17000 44
18000 32
19000 56
25000 34
7500 29
*/

#7


0  

    create table Project (ProjectId int, Description varchar(50));
    insert into Project values (1, 'Chase tail, change directions');
    insert into Project values (2, 'ping-pong ball in clothes dryer');

    create table ProjectResource (ProjectId int, ResourceId int, Name varchar(15));
    insert into ProjectResource values (1, 1, 'Adam');
    insert into ProjectResource values (1, 2, 'Kerry');
    insert into ProjectResource values (1, 3, 'Tom');
    insert into ProjectResource values (2, 4, 'David');
    insert into ProjectResource values (2, 5, 'Jeff');


    SELECT *, 
      (SELECT Name + ' ' AS [text()] 
       FROM ProjectResource pr 
       WHERE pr.ProjectId = p.ProjectId 
       FOR XML PATH ('')) 
    AS ResourceList 
    FROM Project p

-- ProjectId    Description                        ResourceList
-- 1            Chase tail, change directions      Adam Kerry Tom 
-- 2            ping-pong ball in clothes dryer    David Jeff 

#8


0  

The following will enable you to quickly remove the duplicate,null values and return only the valid one as list.

下面将使您能够快速删除重复的空值,并只返回有效的列表。

CREATE TABLE DuplicateTable (Col1 INT)
INSERT INTO DuplicateTable
SELECT 8
UNION ALL
SELECT 1--duplicate
UNION ALL
SELECT 2 --duplicate
UNION ALL
SELECT 1
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION 
SELECT NULL
GO

WITH CTE (COl1,DuplicateCount)
AS
(
SELECT COl1,
ROW_NUMBER() OVER(PARTITION BY COl1 ORDER BY Col1) AS DuplicateCount
FROM DuplicateTable
WHERE (col1 IS NOT NULL) 
)
SELECT COl1
FROM CTE
WHERE DuplicateCount =1
GO

CTE are valid in SQL 2005 , you could then store the values in a temp table and use it with your function.

CTE在SQL 2005中是有效的,然后可以将值存储在临时表中,并将其与函数一起使用。

#9


0  

PASSING TABLE AS PARAMETER IN STORED PROCEDURE

Step 1:

步骤1:

CREATE TABLE [DBO].T_EMPLOYEES_DETAILS ( Id int, Name nvarchar(50), Gender nvarchar(10), Salary int )

创建表(DBO)。T_EMPLOYEES_DETAILS (Id int, Name nvarchar(50),性别nvarchar(10), Salary int)

Step 2:

步骤2:

CREATE TYPE EmpInsertType AS TABLE ( Id int, Name nvarchar(50), Gender nvarchar(10), Salary int )

创建类型EmpInsertType作为表(Id int, Name nvarchar(50),性别nvarchar(10), Salary int)

Step 3:

步骤3:

/* Must add READONLY keyword at end of the variable */

/*必须在变量*/的末尾添加READONLY关键字

CREATE PROC PRC_EmpInsertType @EmployeeInsertType EmpInsertType READONLY AS BEGIN INSERT INTO [DBO].T_EMPLOYEES_DETAILS SELECT * FROM @EmployeeInsertType END

创建PROC PRC_EmpInsertType @EmployeeInsertType EmpInsertType EmpInsertType READONLY作为开始插入到[DBO]。T_EMPLOYEES_DETAILS从@EmployeeInsertType端选择*

Step 4:

步骤4:

DECLARE @EmployeeInsertType EmpInsertType

声明@EmployeeInsertType EmpInsertType

INSERT INTO @EmployeeInsertType VALUES(1,'John','Male',50000) INSERT INTO @EmployeeInsertType VALUES(2,'Praveen','Male',60000) INSERT INTO @EmployeeInsertType VALUES(3,'Chitra','Female',45000) INSERT INTO @EmployeeInsertType VALUES(4,'Mathy','Female',6600) INSERT INTO @EmployeeInsertType VALUES(5,'Sam','Male',50000)

插入到@EmployeeInsertType值(1,'John','Male',50000)插入到@EmployeeInsertType值(2,'Praveen','Male', ' 60000)插入到@EmployeeInsertType值(3,'Chitra','Female' 45000)

EXEC PRC_EmpInsertType @EmployeeInsertType

EXEC PRC_EmpInsertType @EmployeeInsertType

=======================================

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

SELECT * FROM T_EMPLOYEES_DETAILS

SELECT * FROM T_EMPLOYEES_DETAILS

OUTPUT

输出

1 John Male 50000

约翰一书男性50000

2 Praveen Male 60000

Praveen男60000

3 Chitra Female 45000

3 Chitra女45000

4 Mathy Female 6600

数学女6600

5 Sam Male 50000

山姆男50000

#10


-1  

you can do something like this

你可以这样做

/* CREATE USER DEFINED TABLE TYPE */

/*创建用户定义的表类型*/

CREATE TYPE StateMaster AS TABLE
(
 StateCode VARCHAR(2),
 StateDescp VARCHAR(250)
)
GO

/*CREATE FUNCTION WHICH TAKES TABLE AS A PARAMETER */

/*创建以表为参数的函数*/

CREATE FUNCTION TableValuedParameterExample(@TmpTable StateMaster READONLY)
RETURNS  VARCHAR(250)
AS
BEGIN
 DECLARE @StateDescp VARCHAR(250)
 SELECT @StateDescp = StateDescp FROM @TmpTable
 RETURN @StateDescp
END
GO

/*CREATE STORED PROCEDURE WHICH TAKES TABLE AS A PARAMETER */

/*创建以表为参数的存储过程*/

CREATE PROCEDURE TableValuedParameterExample_SP
(
@TmpTable StateMaster READONLY
)
AS
BEGIN
 INSERT INTO StateMst 
  SELECT * FROM @TmpTable
END
GO


BEGIN
/* DECLARE VARIABLE OF TABLE USER DEFINED TYPE */
DECLARE @MyTable StateMaster

/* INSERT DATA INTO TABLE TYPE */
INSERT INTO @MyTable VALUES('11','AndhraPradesh')
INSERT INTO @MyTable VALUES('12','Assam')

/* EXECUTE STORED PROCEDURE */
EXEC TableValuedParameterExample_SP @MyTable
GO

For more details check this link: http://sailajareddy-technical.blogspot.in/2012/09/passing-table-valued-parameter-to.html

要了解更多详细信息,请查看此链接:http://sailajareddy- technical.blogspot.in/2012/09/passtable valueparameter -to.html。

#1


14  

Unfortunately, there is no simple way in SQL Server 2005. Lukasz' answer is correct for SQL Server 2008 though and the feature is long overdue

不幸的是,在SQL Server 2005中没有简单的方法。Lukasz的回答对于SQL Server 2008来说是正确的,这个功能早就应该出现了

Any solution would involve temp tables, or passing in xml/CSV and parsing in the UDF. Example: change to xml, parse in udf

任何解决方案都会涉及临时表,或者在UDF中传递xml/CSV和解析。示例:更改为xml,在udf中解析

DECLARE @psuedotable xml

SELECT
    @psuedotable = ...
FROM
    ...
FOR XML ...

SELECT ... dbo.MyUDF (@psuedotable)

What do you want to do in the bigger picture though? There may be another way to do this...

但是,从更大的角度来看,你想做什么?也许还有别的方法可以做到这一点……

Edit: Why not pass in the query as a string and use a stored proc with output parameter

编辑:为什么不将查询作为字符串传入,并使用带有输出参数的存储proc

Note: this is an untested bit of code, and you'd need to think about SQL injection etc. However, it also satisfies your "one column" requirement and should help you along

注意:这是一段未经测试的代码,您需要考虑SQL注入等。但是,它也满足您的“一列”需求,应该对您有所帮助

CREATE PROC dbo.ToCSV (
    @MyQuery varchar(2000),
    @CSVOut varchar(max)
)
AS
SET NOCOUNT ON

CREATE TABLE #foo (bar varchar(max))

INSERT #foo
EXEC (@MyQuery)

SELECT
    @CSVOut = SUBSTRING(buzz, 2, 2000000000)
FROM
    (
    SELECT 
        bar -- maybe CAST(bar AS varchar(max))??
    FROM 
        #foo
    FOR XML PATH (',')
    ) fizz(buzz)
GO

#2


62  

You can, however no any table. From documentation:

你可以,但是没有任何桌子。从文档:

For Transact-SQL functions, all data types, including CLR user-defined types and user-defined table types, are allowed except the timestamp data type.

对于Transact-SQL函数,除了时间戳数据类型之外,所有数据类型(包括CLR用户定义类型和用户定义表类型)都是允许的。

You can use user-defined table types.

您可以使用用户定义的表类型。

Example of user-defined table type:

用户定义的表类型示例:

CREATE TYPE TableType 
AS TABLE (LocationName VARCHAR(50))
GO 

DECLARE @myTable TableType
INSERT INTO @myTable(LocationName) VALUES('aaa')
SELECT * FROM @myTable

So what you can do is to define your table type, for example TableType and define funcion which takes the parameter of this type.An example function:

所以你能做的就是定义你的表类型,例如表类型和定义函数它取这个类型的参数。功能:一个例子

CREATE FUNCTION Example( @TableName TableType READONLY)
RETURNS VARCHAR(50)
AS
BEGIN
    DECLARE @name VARCHAR(50)

    SELECT TOP 1 @name = LocationName FROM @TableName
    RETURN @name
END

The parameter has to be READONLY. And example usage:

参数必须是只读的。和示例用法:

DECLARE @myTable TableType
INSERT INTO @myTable(LocationName) VALUES('aaa')
SELECT * FROM @myTable

SELECT dbo.Example(@myTable)

Depending of what you want achieve you can modify this code.

根据您想要实现的目标,您可以修改此代码。

EDIT: If you have a data in a table you may create a variable:

编辑:如果表中有数据,可以创建一个变量:

DECLARE @myTable TableType

And take data from your table to the variable

从表中取数据到变量中

INSERT INTO @myTable(field_name)
SELECT field_name_2 FROm my_other_table

#3


2  

Cutting to the bottom line, you want a query like SELECT x FROM y to be passed into a function that returns the values as a comma separated string.

对于底线,您需要一个查询,比如从y中选择x,将其传递给一个函数,该函数返回值作为逗号分隔的字符串。

As has already been explained you can do this by creating a table type and passing a UDT into the function, but this needs a multi-line statement.

正如已经解释的那样,您可以通过创建一个表类型并将UDT传递到函数来实现这一点,但是这需要一个多行语句。

You can pass XML around without declaring a typed table, but this seems to need a xml variable which is still a multi-line statement i.e.

您可以在不声明类型化表的情况下传递XML,但是这似乎需要一个XML变量,它仍然是一个多行语句。

DECLARE @MyXML XML = (SELECT x FROM y FOR XML RAW);
SELECT Dbo.CreateCSV(@MyXml);

The "FOR XML RAW" makes the SQL give you it's result set as some xml.

“FOR XML RAW”使SQL将其结果设置为一些XML。

But you can bypass the variable using Cast(... AS XML). Then it's just a matter of some XQuery and a little concatenation trick:

但是可以使用Cast来绕过变量(……)作为XML)。然后就是一些XQuery和一些连接技巧:

CREATE FUNCTION CreateCSV (@MyXML XML) 
RETURNS VARCHAR(MAX)
BEGIN
    DECLARE @listStr VARCHAR(MAX);
    SELECT 
            @listStr = 
                COALESCE(@listStr+',' ,'') + 
                c.value('@Value[1]','nvarchar(max)') 
        FROM @myxml.nodes('/row') as T(c)
    RETURN @listStr
END
GO

-- And you call it like this:
SELECT Dbo.CreateCSV(CAST((    SELECT x FROM y    FOR XML RAW) AS XML));

-- Or a working example
SELECT Dbo.CreateCSV(CAST((
        SELECT DISTINCT number AS Value 
        FROM master..spt_values 
        WHERE type = 'P' 
            AND number <= 20
    FOR XML RAW) AS XML));

As long as you use FOR XML RAW all you need do is alias the column you want as Value, as this is hard coded in the function.

只要您对XML RAW使用,您所需要做的就是将您想要的列别名为Value,因为这是函数中的硬编码。

#4


2  

Step 1: Create a Type as Table with name TableType that will accept a table having one varchar column

步骤1:创建一个名为TableType的表,它将接受一个具有一个varchar列的表。

create type TableType
as table ([value] varchar(100) null)

Step 2: Create a function that will accept above declared TableType as Table-Valued Parameter and String Value as Separator

步骤2:创建一个函数,该函数将接受上面声明的表类型作为表值参数,字符串值作为分隔符

create function dbo.fn_get_string_with_delimeter (@table TableType readonly,@Separator varchar(5))
returns varchar(500)
As
begin

    declare @return varchar(500)

    set @return = stuff((select @Separator + value from @table for xml path('')),1,1,'')

    return @return

end

Step 3: Pass table with one varchar column to the user-defined type TableType and ',' as separator in the function

步骤3:将一个varchar列的表传递给用户定义的类型表类型和',',作为函数中的分隔符

select dbo.fn_get_string_with_delimeter(@tab, ',')

#5


1  

I've been dealing with a very similar problem and have been able to achieve what I was looking for, even though I'm using SQL Server 2000. I know it is an old question, but think its valid to post here the solution since there should be others like me that use old versions and still need help.

我一直在处理一个非常相似的问题,并且能够实现我所期望的,即使我正在使用SQL Server 2000。我知道这是一个老问题,但我认为在这里发布解决方案是有效的,因为应该有像我这样的人使用旧版本,仍然需要帮助。

Here's the trick: SQL Server won't accept passing a table to a UDF, nor you can pass a T-SQL query so the function creates a temp table or even calls a stored procedure to do that. So, instead, I've created a reserved table, which I called xtList. This will hold the list of values (1 column, as needed) to work with.

这里有一个诀窍:SQL Server不接受将表传递给UDF,也不能传递T-SQL查询,因此该函数创建一个临时表,甚至调用一个存储过程来实现这一点。因此,我创建了一个保留表,我将其命名为xtList。这将包含用于处理的值列表(需要的1列)。

CREATE TABLE [dbo].[xtList](
    [List] [varchar](1000) NULL
) ON [PRIMARY]

Then, a stored procedure to populate the list. This is not strictly necessary, but I think is very usefull and best practice.

然后,填充列表的存储过程。这不是绝对必要的,但我认为这是非常有用的和最好的实践。

-- =============================================
-- Author:      Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE PROCEDURE [dbo].[xpCreateList]
    @ListQuery varchar(2000)
AS
BEGIN
    SET NOCOUNT ON;

  DELETE FROM xtList

  INSERT INTO xtList
    EXEC(@ListQuery)
END

Now, just deal with the list in any way you want, using the xtList. You can use in a procedure (for executing several T-SQL commands), scalar functions (for retrieving several strings) or multi-statement table-valued functions (retrieves the strings but like it was inside a table, 1 string per row). For any of that, you'll need cursors:

现在,用你想要的任何方式来处理列表,使用并置列表。您可以在过程(用于执行多个T-SQL命令)、标量函数(用于检索多个字符串)或多语句表值函数(检索字符串,但像在表中一样,每行一个字符串)中使用。其中任何一种都需要游标:

DECLARE @Item varchar(100)
DECLARE cList CURSOR DYNAMIC
  FOR (SELECT * FROM xtList WHERE List is not NULL)
  OPEN cList

FETCH FIRST FROM cList INTO @Item
WHILE @@FETCH_STATUS = 0 BEGIN

  << desired action with values >>

FETCH NEXT FROM cList INTO @Item
END
CLOSE cList
DEALLOCATE cList

The desired action would be as follows, depending on which type of object created:

所需的行动将如下,视所创建对象的类型而定:

Stored procedures

存储过程

-- =============================================
-- Author:      Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE PROCEDURE [dbo].[xpProcreateExec]
(
    @Cmd varchar(8000),
    @ReplaceWith varchar(1000)
)
AS
BEGIN
  DECLARE @Query varchar(8000)

  << cursor start >>
    SET @Query = REPLACE(@Cmd,@ReplaceWith,@Item)
    EXEC(@Query)
  << cursor end >>
END

/* EXAMPLES

  (List A,B,C)

  Query = 'SELECT x FROM table'
    with EXEC xpProcreateExec(Query,'x') turns into
  SELECT A FROM table
  SELECT B FROM table
  SELECT C FROM table

  Cmd = 'EXEC procedure ''arg''' --whatchout for wrong quotes, since it executes as dynamic SQL
    with EXEC xpProcreateExec(Cmd,'arg') turns into
  EXEC procedure 'A'
  EXEC procedure 'B'
  EXEC procedure 'C'

*/

Scalar functions

标量函数

-- =============================================
-- Author:      Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE FUNCTION [dbo].[xfProcreateStr]
(
    @OriginalText varchar(8000),
    @ReplaceWith varchar(1000)
)
RETURNS varchar(8000)
AS
BEGIN
    DECLARE @Result varchar(8000)

  SET @Result = ''
  << cursor start >>
    SET @Result = @Result + REPLACE(@OriginalText,@ReplaceWith,@Item) + char(13) + char(10)
  << cursor end >>

    RETURN @Result
END

/* EXAMPLE

  (List A,B,C)

  Text = 'Access provided for user x'
    with "SELECT dbo.xfProcreateStr(Text,'x')" turns into
  'Access provided for user A
  Access provided for user B
  Access provided for user C'

*/

Multi-statement table-valued functions

Multi-statement表值函数

-- =============================================
-- Author:      Zark Khullah
-- Create date: 20/06/2014
-- =============================================
CREATE FUNCTION [dbo].[xfProcreateInRows]
(
    @OriginalText varchar(8000),
    @ReplaceWith varchar(1000)
)
RETURNS 
@Texts TABLE 
(
    Text varchar(2000)
)
AS
BEGIN
  << cursor start >>
      INSERT INTO @Texts VALUES(REPLACE(@OriginalText,@ReplaceWith,@Item))
  << cursor end >>
END

/* EXAMPLE

  (List A,B,C)

  Text = 'Access provided for user x'
    with "SELECT * FROM dbo.xfProcreateInRow(Text,'x')" returns rows
  'Access provided for user A'
  'Access provided for user B'
  'Access provided for user C'

*/

#6


0  

To obtain the column count on a table, use this:

要获取表上的列计数,请使用以下方法:

select count(id) from syscolumns where id = object_id('tablename')

and to pass a table to a function, try XML as show here:

要将表传递给函数,请尝试如下所示的XML:

create function dbo.ReadXml (@xmlMatrix xml)
returns table
as
return
( select
t.value('./@Salary', 'integer') as Salary,
t.value('./@Age', 'integer') as Age
from @xmlMatrix.nodes('//row') x(t)
)
go

declare @source table
( Salary integer,
age tinyint
)
insert into @source
select 10000, 25 union all
select 15000, 27 union all
select 12000, 18 union all
select 15000, 36 union all
select 16000, 57 union all
select 17000, 44 union all
select 18000, 32 union all
select 19000, 56 union all
select 25000, 34 union all
select 7500, 29
--select * from @source

declare @functionArgument xml

select @functionArgument =
( select
Salary as [row/@Salary],
Age as [row/@Age]
from @source
for xml path('')
)
--select @functionArgument as [@functionArgument]

select * from readXml(@functionArgument)

/* -------- Sample Output: --------
Salary Age
----------- -----------
10000 25
15000 27
12000 18
15000 36
16000 57
17000 44
18000 32
19000 56
25000 34
7500 29
*/

#7


0  

    create table Project (ProjectId int, Description varchar(50));
    insert into Project values (1, 'Chase tail, change directions');
    insert into Project values (2, 'ping-pong ball in clothes dryer');

    create table ProjectResource (ProjectId int, ResourceId int, Name varchar(15));
    insert into ProjectResource values (1, 1, 'Adam');
    insert into ProjectResource values (1, 2, 'Kerry');
    insert into ProjectResource values (1, 3, 'Tom');
    insert into ProjectResource values (2, 4, 'David');
    insert into ProjectResource values (2, 5, 'Jeff');


    SELECT *, 
      (SELECT Name + ' ' AS [text()] 
       FROM ProjectResource pr 
       WHERE pr.ProjectId = p.ProjectId 
       FOR XML PATH ('')) 
    AS ResourceList 
    FROM Project p

-- ProjectId    Description                        ResourceList
-- 1            Chase tail, change directions      Adam Kerry Tom 
-- 2            ping-pong ball in clothes dryer    David Jeff 

#8


0  

The following will enable you to quickly remove the duplicate,null values and return only the valid one as list.

下面将使您能够快速删除重复的空值,并只返回有效的列表。

CREATE TABLE DuplicateTable (Col1 INT)
INSERT INTO DuplicateTable
SELECT 8
UNION ALL
SELECT 1--duplicate
UNION ALL
SELECT 2 --duplicate
UNION ALL
SELECT 1
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION 
SELECT NULL
GO

WITH CTE (COl1,DuplicateCount)
AS
(
SELECT COl1,
ROW_NUMBER() OVER(PARTITION BY COl1 ORDER BY Col1) AS DuplicateCount
FROM DuplicateTable
WHERE (col1 IS NOT NULL) 
)
SELECT COl1
FROM CTE
WHERE DuplicateCount =1
GO

CTE are valid in SQL 2005 , you could then store the values in a temp table and use it with your function.

CTE在SQL 2005中是有效的,然后可以将值存储在临时表中,并将其与函数一起使用。

#9


0  

PASSING TABLE AS PARAMETER IN STORED PROCEDURE

Step 1:

步骤1:

CREATE TABLE [DBO].T_EMPLOYEES_DETAILS ( Id int, Name nvarchar(50), Gender nvarchar(10), Salary int )

创建表(DBO)。T_EMPLOYEES_DETAILS (Id int, Name nvarchar(50),性别nvarchar(10), Salary int)

Step 2:

步骤2:

CREATE TYPE EmpInsertType AS TABLE ( Id int, Name nvarchar(50), Gender nvarchar(10), Salary int )

创建类型EmpInsertType作为表(Id int, Name nvarchar(50),性别nvarchar(10), Salary int)

Step 3:

步骤3:

/* Must add READONLY keyword at end of the variable */

/*必须在变量*/的末尾添加READONLY关键字

CREATE PROC PRC_EmpInsertType @EmployeeInsertType EmpInsertType READONLY AS BEGIN INSERT INTO [DBO].T_EMPLOYEES_DETAILS SELECT * FROM @EmployeeInsertType END

创建PROC PRC_EmpInsertType @EmployeeInsertType EmpInsertType EmpInsertType READONLY作为开始插入到[DBO]。T_EMPLOYEES_DETAILS从@EmployeeInsertType端选择*

Step 4:

步骤4:

DECLARE @EmployeeInsertType EmpInsertType

声明@EmployeeInsertType EmpInsertType

INSERT INTO @EmployeeInsertType VALUES(1,'John','Male',50000) INSERT INTO @EmployeeInsertType VALUES(2,'Praveen','Male',60000) INSERT INTO @EmployeeInsertType VALUES(3,'Chitra','Female',45000) INSERT INTO @EmployeeInsertType VALUES(4,'Mathy','Female',6600) INSERT INTO @EmployeeInsertType VALUES(5,'Sam','Male',50000)

插入到@EmployeeInsertType值(1,'John','Male',50000)插入到@EmployeeInsertType值(2,'Praveen','Male', ' 60000)插入到@EmployeeInsertType值(3,'Chitra','Female' 45000)

EXEC PRC_EmpInsertType @EmployeeInsertType

EXEC PRC_EmpInsertType @EmployeeInsertType

=======================================

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

SELECT * FROM T_EMPLOYEES_DETAILS

SELECT * FROM T_EMPLOYEES_DETAILS

OUTPUT

输出

1 John Male 50000

约翰一书男性50000

2 Praveen Male 60000

Praveen男60000

3 Chitra Female 45000

3 Chitra女45000

4 Mathy Female 6600

数学女6600

5 Sam Male 50000

山姆男50000

#10


-1  

you can do something like this

你可以这样做

/* CREATE USER DEFINED TABLE TYPE */

/*创建用户定义的表类型*/

CREATE TYPE StateMaster AS TABLE
(
 StateCode VARCHAR(2),
 StateDescp VARCHAR(250)
)
GO

/*CREATE FUNCTION WHICH TAKES TABLE AS A PARAMETER */

/*创建以表为参数的函数*/

CREATE FUNCTION TableValuedParameterExample(@TmpTable StateMaster READONLY)
RETURNS  VARCHAR(250)
AS
BEGIN
 DECLARE @StateDescp VARCHAR(250)
 SELECT @StateDescp = StateDescp FROM @TmpTable
 RETURN @StateDescp
END
GO

/*CREATE STORED PROCEDURE WHICH TAKES TABLE AS A PARAMETER */

/*创建以表为参数的存储过程*/

CREATE PROCEDURE TableValuedParameterExample_SP
(
@TmpTable StateMaster READONLY
)
AS
BEGIN
 INSERT INTO StateMst 
  SELECT * FROM @TmpTable
END
GO


BEGIN
/* DECLARE VARIABLE OF TABLE USER DEFINED TYPE */
DECLARE @MyTable StateMaster

/* INSERT DATA INTO TABLE TYPE */
INSERT INTO @MyTable VALUES('11','AndhraPradesh')
INSERT INTO @MyTable VALUES('12','Assam')

/* EXECUTE STORED PROCEDURE */
EXEC TableValuedParameterExample_SP @MyTable
GO

For more details check this link: http://sailajareddy-technical.blogspot.in/2012/09/passing-table-valued-parameter-to.html

要了解更多详细信息,请查看此链接:http://sailajareddy- technical.blogspot.in/2012/09/passtable valueparameter -to.html。