문제

테이블을 스케일러 UDF로 매개 변수로 전달하고 싶습니다.

또한 매개 변수를 하나의 열만 한 테이블로 제한하는 것을 선호합니다. (선택 과목)

이게 가능해?

편집하다

테이블 이름을 전달하고 싶지 않아 데이터 테이블을 전달하고 싶습니다 (내가 추정하는 참조로)

편집하다

스케일러 UDF가 기본적으로 값 테이블을 가져 와서 행의 CSV 목록을 반환하기를 원합니다.

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

돌아올 것입니다

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

그래도 테이블에서 필터링을하고 싶습니다. 즉, 널이 없도록하고 복제물이 없는지 확인합니다. 나는 다음의 선을 따라 무언가를 기대하고 있었다.

SELECT dbo.MyFunction(SELECT DISTINCT myDate FROM myTable WHERE myDate IS NOT NULL)
도움이 되었습니까?

해결책

불행히도 SQL Server 2005에는 간단한 방법이 없습니다. Lukasz의 답변은 SQL Server 2008에 맞습니다. 기능은 다음과 같습니다. 기한이 지난

모든 솔루션에는 온도 테이블이 포함되거나 XML/CSV를 통과하고 UDF에서 구문 분석합니다. 예 : XML로 변경, UDF의 구문 분석

DECLARE @psuedotable xml

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

SELECT ... dbo.MyUDF (@psuedotable)

그래도 더 큰 그림에서 무엇을하고 싶습니까? 이를 수행하는 또 다른 방법이있을 수 있습니다 ...

편집 : 쿼리를 문자열로 전달하고 출력 매개 변수가있는 저장된 Proc를 사용하지 않겠습니까?

참고 : 이것은 테스트되지 않은 코드이며 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

다른 팁

그러나 당신은 어떤 테이블도 할 수 없습니다. 문서 :

Transact-SQL 기능의 경우 Timestamp 데이터 유형을 제외한 CLR 사용자 정의 유형 및 사용자 정의 테이블 유형을 포함한 모든 데이터 유형이 허용됩니다.

당신이 사용할 수있는 사용자 정의 테이블 유형.

사용자 정의 테이블 유형의 예 :

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

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

예를 들어 테이블 유형을 정의하는 것입니다. TableType 이 유형의 매개 변수를 취하는 기능을 정의하십시오. 예제 기능 :

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

매개 변수는 준비되어 있어야합니다. 및 예제 사용 :

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

SELECT dbo.Example(@myTable)

달성하려는 것에 따라이 코드를 수정할 수 있습니다.

편집하다:테이블에 데이터가있는 경우 변수를 만들 수 있습니다.

DECLARE @myTable TableType

테이블에서 변수로 데이터를 가져옵니다

INSERT INTO @myTable(field_name)
SELECT field_name_2 FROm my_other_table

1 단계: varchar 열 하나가있는 테이블을 허용하는 이름 탁상이있는 테이블로 유형을 만듭니다.

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

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

3 단계: 하나의 varchar 열이있는 테이블을 사용자 정의 유형 타입으로 전달하고 '함수의 분리기로', ',', ',', ',', '

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

결론으로 자르면 y의 select x와 같은 쿼리가 값을 쉼표로 분리 된 문자열로 반환하는 함수로 전달되기를 원합니다.

이미 설명 된 바와 같이 테이블 유형을 만들고 UDT를 함수로 전달 하여이 작업을 수행 할 수 있지만 멀티 라인 문이 필요합니다.

입력 된 테이블을 선언하지 않고 XML을 통과 할 수 있지만 여전히 멀티 라인 문 (IE) 인 XML 변수가 필요합니다.

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

"for xml raw"는 SQL이 일부 XML로 결과 세트를 제공합니다.

그러나 CAST (... as 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));

XML RAW에 사용하는 한, 당신이 필요한 모든 것은 값으로 원하는 열을 값으로 하드 코딩하기 때문에 값으로 원하는 열을 사용하기 만하면됩니다.

나는 매우 비슷한 문제를 다루고 있었고 SQL Server 2000을 사용하고 있지만 찾고 있던 것을 달성 할 수있었습니다. 오래된 질문이지만 여기에 솔루션을 게시하는 것이 유효하다고 생각합니다. 오래된 버전을 사용하고 여전히 도움이 필요한 나와 같은 다른 사람들이 있어야합니다.

트릭은 다음과 같습니다. SQL Server는 테이블을 UDF로 전달하지 않으며 T-SQL 쿼리를 전달하여 함수가 온도 테이블을 생성하거나 저장 프로 시저를 호출하여이를 수행 할 수 있습니다. 대신, XTList라고 불리는 예약 테이블을 만들었습니다. 이것은 작업 할 값 목록 (필요에 따라 1 열)을 보유합니다.

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

그런 다음 목록을 채우기위한 저장된 절차. 이것은 엄격하게 필요하지 않지만 매우 유용하고 모범 사례라고 생각합니다.

-- =============================================
-- 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

이제 XTList를 사용하여 원하는 방식으로 목록을 처리하십시오. 프로 시저 (여러 t-sql 명령을 실행하기 위해), 스칼라 함수 (여러 문자열 검색) 또는 다중 상태 테이블 값 함수 (문자열을 검색하지만 표 안에서 1 줄 당 1 줄)에서 사용할 수 있습니다. 그 중 하나라도 커서가 필요합니다.

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

원하는 조치는 어떤 유형의 객체를 생성했는지에 따라 다음과 같습니다.

저장된 절차

-- =============================================
-- 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'

*/

스칼라 기능

-- =============================================
-- 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'

*/

다중 종료 테이블 값 기능

-- =============================================
-- 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'

*/

테이블에서 열 계산을 얻으려면 다음을 사용하십시오.

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

테이블을 함수로 전달하려면 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
*/
    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 

다음을 사용하면 복제 된 널 값을 빠르게 제거하고 유효한 값 만 목록으로 반환 할 수 있습니다.

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는 SQL 2005에서 유효하며 값을 임시 테이블에 저장하고 기능과 함께 사용할 수 있습니다.

저장 프로 시저에서 매개 변수로 통과하는 테이블

1 단계:

테이블 만들기 [dbo] .t_employees_details (id int, name nvarchar (50), Gender nvarchar (10), Salary Int)

2 단계:

타입 EmpinsertType 생성 테이블 (ID int, name nvarchar (50), Gender Nvarchar (10), Salary Int)

3 단계 : :

/ * 변수 끝에 readonly 키워드를 추가해야합니다 */

proc prc_empinserttype @employeeinserttype empinserttype readonly [dbo] .t_employees_details select * from @employeeinserttype end

Step 4:

@employeeinesttype empinserttype를 선언하십시오

@employeeinserttype 값 (1, 'John', 'Male', 50000)에 삽입 @employeeinsertType 값 (2, 'Praveen', 'Male', 60000)에 삽입 ', 45000) @employeeinserttype 값 (4,'Mathy ','Female ', 6600)에 삽입하여 @employeeinserttype 값 (5,'Sam ','Male ', 50000)에 삽입

exec prc_empinserttype @employeeinserttype

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

t_employees_details에서 *를 선택하십시오

산출

1 John Male 50000

2 Praveen Male 60000

3 Chitra 여성 45000

4 수학 여성 6600

5 Sam Male 50000

당신은 이런 일을 할 수 있습니다

/ * 사용자 정의 테이블 유형 생성 */

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

/ *테이블을 매개 변수로 가져 오는 함수 작성 */

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 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

자세한 내용은이 링크를 확인하십시오. http://sailajareddy-technical.blogspot.in/2012/09/Passing-table-valued-parameter-to--html

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top