2016-12-28 29 views
-1

我有这个表值的函数,它根据分隔符分割字符串来创建表。Sqlserver 2014:无法在动态查询中使用表值函数

USE [sysmon] 
GO 
/****** Object: UserDefinedFunction [dbo].[ParseString3] Script Date: 12/28/2016 3:49:06 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER OFF 
GO 


ALTER FUNCTION [dbo].[ParseString3] (@String VARCHAR(MAX), @Delimiter VARCHAR(10)) 
RETURNS TABLE 
AS 

RETURN (
SELECT Ident, StringValue FROM 
    (
     SELECT Num as Ident, 
      CASE 
       WHEN DATALENGTH(@delimiter) = 0 or @delimiter IS NULL 
        THEN SUBSTRING(@string, num, 1) 
      ELSE 
       LTRIM(RTRIM(SUBSTRING(@String, 
        CASE 
         WHEN (Num = 1 AND SUBSTRING(@String,num ,DATALENGTH(@delimiter)) <> @delimiter) THEN 1 
         ELSE Num + DATALENGTH(@delimiter) 
        END, 
        CASE CHARINDEX(@Delimiter, @String, Num + DATALENGTH(@delimiter)) 
         WHEN 0 THEN LEN(@String) - Num + DATALENGTH(@delimiter) 
         ELSE CHARINDEX(@Delimiter, @String, Num + DATALENGTH(@delimiter)) - Num - 
          CASE 
           WHEN Num > 1 OR (Num = 1 AND SUBSTRING(@String,num ,DATALENGTH(@delimiter)) = @delimiter) 
             THEN DATALENGTH(@delimiter) 
           ELSE 0 
          END 
         END 
        ))) 
       End AS StringValue 
     FROM sysmon.dbo.Numbers 
     WHERE Num <= LEN(@String) 
      AND ( 
        SUBSTRING(@String, Num, DATALENGTH(ISNULL(@delimiter,''))) = @Delimiter 
        OR Num = 1 
        OR DATALENGTH(ISNULL(@delimiter,'')) = 0 
       ) 
    ) R WHERE DATALENGTH(StringValue) <> 0 
) 

现在我创建下面的动态查询

declare @abc nvarchar(500) 

     set @abc = 'select distinct stringvalue, ' + [sysmon].[dbo].[feedmapping]('sungard') + 
      'from ' + [sysmon].[dbo].[parseString3]('599362,16570,568838',',') + 
      ' inner join dbname.dbo.tablename 
      on stringvalue = tablecolumn' 
exec sp_executesql @abc 

其中feedmapping是另一个标量值的功能

USE [sysmon] 
GO 
/****** Object: UserDefinedFunction [dbo].[FeedMapping] Script Date: 12/28/2016 4:07:59 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER FUNCTION [dbo].[FeedMapping](@feedName Varchar(20)) 
RETURNS VARCHAR(20) 
AS 
BEGIN 
    DECLARE @ret VARCHAR(20) 
    IF (@feedname = 'SunGard') 
     set @ret = 'SungardSymbol' 
    ELSE IF (@feedname = 'xxxx') 
     set @ret = 'yyyyyyy' 
    ELSE IF (@feedname = 'aaaaa') 
     set @ret = 'ccccccc' 
    return @ret 
END 

在运行它给我下面的错误

无法找到列“sysmon”或用户d已定义函数或 聚合“sysmon.dbo.parseString3”,或名称不明确。

请帮

+1

为什么PLSQL标签? – jarlh

+0

你能打印@abc吗?并粘贴在这里? –

+0

@ user2611539查询中的动态值是什么? –

回答

0

动态SQL启动新会话(SID)。动态sql会话中不提供具有当前权限的会话。您无权对[sysmon]进行响应。

还有一件事。你可以用简单的方法拆分字符串。尝试使用代码:

CREATE FUNCTION [dbo].[str__split](
    @str   NVARCHAR(MAX) 
    ,@delimiter  NVARCHAR(MAX) 
) 
RETURNS @split TABLE(
    [str] NVARCHAR(MAX) 
) 
AS 
BEGIN 

    INSERT INTO @split(
     [str] 
    ) 
    SELECT 
     [X].[C].[value]('(./text())[1]', 'nvarchar(4000)') 
    FROM 
     ( 
      SELECT 
       [X] = CONVERT(XML, '<i>' + REPLACE(@str, @delimiter, '</i><i>') + '</i>').query('.') 
     )     AS [A] 
    CROSS APPLY 
     [X].[nodes]('i') AS [X]([C]); 

    RETURN; 

END 

为了解决你的问题,我可以推荐这个:

  1. 没有登录创建数据库用户(代理用户)授予访问权限
  2. 到代理用户的[ sysmon]创建存储过程,专用于
  3. 动态sql调用,并在头exec范围内声明为代理用户。

其他,不好,但快速的方法:

CREATE PROCEDURE dbo.sql_dynamic 
WITH EXECUTE AS OWNER 
--- your dynamic sql call ---- 

附:现在被清除,问题是与记录集字符串连接。

你的第一个函数返回字符串。它可以与剩余的字符串连接。但其次,表值函数返回记录集。您不能连接字符串与记录集。糟糕的做法。您需要根据您的表值函数记录集制作汇总字符串,然后将它与剩余的字符串连接起来。

+0

感谢您的回复。但其成功运行的标量值函数'feemapping'也存在于sysmon内部。那为什么它不能运行表值函数? – user2611539

+0

你的第一个函数返回字符串。它可以与剩余的字符串连接。但其次,表值函数返回记录集。您不能连接字符串与记录集。糟糕的做法。您需要根据您的表值函数记录集制作汇总字符串,然后将它与剩余的字符串连接起来。 – Juozas

+0

我不明白你想达到什么目的。也许你根本不需要动态sql。什么是“表列”?字符串,表列或..? \t选择不同 \t \t [A]。[stringValue的] \t \t,[SYSMON] [DBO]。[feedmapping]( '金仕达') \t从 \t \t [SYSMON] [DBO]。[ parseString3]( '599362,16570,568838', '')\t \t作为[A] \t内加入 \t \t为[dbname] [DBO]。[表名] \t \t \t \t \t \t \t \t \t \t作为[B] \t其中 \t \t \t [A] [stringValue的] ='TableColumn的。 – Juozas

0

尝试这种方式

DECLARE @sql  NVARCHAR(4000)= '', 
     @col_name VARCHAR(128), 
     @ps_input VARCHAR(8000)= '599362,16570,568838' 

SELECT @col_name = [sysmon].[dbo].[Feedmapping]('sungard') 

SET @sql = ' 
SELECT DISTINCT stringvalue,' + @col_name+ ' 
FROM [sysmon].[dbo].[Parsestring3](@ps_input, '','') 
     INNER JOIN dbname.dbo.tablename 
       ON stringvalue = tablecolumn' 

EXEC Sp_executesql 
    @sql, 
    N'@ps_input varchar(8000)', -- Declaration 
    @[email protected]_input -- To pass the input inside dynamic query 
+0

感谢您的回复。在这种情况下,它将值“sungardsymbol”(作为feedmapping函数返回)视为常量,但我想在我的select查询中将它用作字段名称(它是tablename的一个字段之一)。 – user2611539

+0

@ user2611539 - 更新检查现在 –

+0

大。它的工作原理..谢谢..你可以让我简单地告诉我们,为什么我们在执行时再次声明并分配了@ps_input? – user2611539

相关问题