我正在使用SQL Server 2008,我正在努力学习如何在用户定义的内联表值函数上正确调用用户定义的内联表值函数(也就是说,因为每个人都期望标量或标量作为输入和输出表,我想学习如何通过传递另一个表来正确调用一个表,然后将每一行视为其标量输入。)
我最近发布了几个与此相关的问题,但我认为我不够清楚,并没有充分地将问题封装到干净地展示它。我现在准备了适当的语句,以便为有兴趣帮助必要的表,视图,函数和SELECT输出的人提供帮助,通过执行下面的查询来看到问题出现在他们面前。
我可以用几种方式来表达核心问题,从这里和其他论坛,我可以说我很难清楚地表达它。我将在这里用几种方式来表达它,但这些都是相同的问题,用不同的方式表达,因此来自不同背景的人可以更容易地理解我。
如何正确编写下面的“imageFileNameFromAddress”函数,使其按预期工作;也就是说,意图是它使用与“bookAndPageFromAddress”相同的输入,并使用bookAndPageFromAddress和imageFileNameFromBookPage,将输入传递给第一个,然后将其输出传递给第二个,并返回第二个输出?
为什么下面底部的第三个SELECT语句提供与第二个不同的结果,如何修复底层函数以提供相同的结果,而不重复其他函数的代码?
imageFileNameFromAddress中OUTER APPLY调用的正确语法是什么,以使其输出不为空?
警告:下面的代码构造了必要的表,视图和函数,以便在问题存在的情况下首先将它们删除,所以请首先检查以确保不丢弃任何自己的内容!最后三个SELECTS证明了这个问题;最后两个SELECTS应该有相同的输出,但不要 - 第一个(最后两个,所以三个中间)是一个三行的字符串表,最后一个是一个只包含NULL的行表
USE [TOM_GIS]
GO
IF OBJECT_ID(N'[dbo].[constant]', N'U') IS NOT NULL
DROP TABLE [dbo].[constant]
CREATE TABLE [dbo].[constant]
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
BOOK varchar(5),
PAGE varchar(5),
DocID numeric(8, 0)
)
INSERT INTO [dbo].[constant]
VALUES(' 4043',' 125', 576030)
GO
IF OBJECT_ID(N'[dbo].[images]', N'U') IS NOT NULL
DROP TABLE [dbo].[images]
CREATE TABLE [dbo].[images]
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
DocID numeric(8, 0),
ImageID numeric(12,0)
)
INSERT INTO [dbo].[images] VALUES(576030, 1589666);
INSERT INTO [dbo].[images] VALUES(576030, 1589667);
INSERT INTO [dbo].[images] VALUES(576030, 1589668);
GO
IF OBJECT_ID(N'[dbo].[addressBookPage]', N'U') IS NOT NULL
DROP TABLE [dbo].[addressBookPage]
CREATE TABLE [dbo].[addressBookPage]
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
PARCEL_ADDRESS nvarchar(50),
BOOK nchar(10),
PAGE nchar(10),
)
INSERT INTO [dbo].[addressBookPage]
VALUES('155 CENTER STREET','4043', '125')
GO
IF OBJECT_ID(N'[dbo].[vw_quindraco]') IS NOT NULL
DROP VIEW [dbo].[vw_quindraco]
GO
CREATE VIEW [dbo].[vw_quindraco]
AS
WITH files AS (SELECT RIGHT('00000000' + LTRIM(STR(c.DocID)), 8) AS PathInfo
,RIGHT('0000000000' + LTRIM(STR(i.ImageID)), 12) AS FileName
,ltrim(c.Book) as Book
,ltrim(c.Page) as Page
FROM [dbo].[constant] AS c INNER JOIN
[dbo].[images] AS i ON c.DocID = i.DocID)
SELECT 'Images/' + SUBSTRING(PathInfo, 1, 2) + '/' + SUBSTRING(PathInfo, 3, 2) + '/' + SUBSTRING(PathInfo, 5, 2)
+ '/' + RIGHT(PathInfo, 8) + '/' + FileName + '.tif' AS FullFileName
,Book
,Page
FROM files AS files_1
GO
IF OBJECT_ID(N'[dbo].[bookAndPageFromAddress]') IS NOT NULL
DROP FUNCTION [dbo].[bookAndPageFromAddress];
GO
CREATE FUNCTION [dbo].[bookAndPageFromAddress] (@address NVARCHAR(max))
RETURNS TABLE AS RETURN(
SELECT PARCEL_ADDRESS AS Address, Book, Page
FROM [dbo].[addressBookPage]
WHERE PARCEL_ADDRESS like '%' + @address + '%'
);
GO
IF OBJECT_ID(N'[dbo].[imageFileNameFromBookPage]') IS NOT NULL
DROP FUNCTION [dbo].[imageFileNameFromBookPage];
GO
CREATE FUNCTION [dbo].[imageFileNameFromBookPage] (@book nvarchar(max), @page nvarchar(max))
RETURNS TABLE AS RETURN(
SELECT i.FullFileName
FROM [dbo].[vw_quindraco] i
WHERE i.Book like @book
AND i.Page like @page
);
GO
IF OBJECT_ID(N'[dbo].[imageFileNameFromAddress]') IS NOT NULL
DROP FUNCTION [dbo].[imageFileNameFromAddress];
GO
CREATE FUNCTION [dbo].[imageFileNameFromAddress] (@address NVARCHAR(max))
RETURNS TABLE AS RETURN(
SELECT *
FROM [dbo].[bookAndPageFromAddress](@address) addresses
OUTER APPLY [dbo].[imageFileNameFromBookPage](addresses.Book, addresses.Page) foo
);
GO
SELECT Book,Page FROM [dbo].[bookAndPageFromAddress]('155 Center Street');
SELECT FullFileName FROM [dbo].[imageFileNameFromBookPage]('4043','125');
SELECT FullFileName FROM [dbo].[imageFileNameFromAddress]('155 Center Street')
答案 0 :(得分:1)
您的表格字段为nchar
,并且您使用的是Like
。
因为它是nchar
,所以该值用空格填充到声明的长度(10)
因为它是Like
,所以空格被认为是匹配的必要部分,而相等运算符=
将忽略尾随空格。
由于表和函数参数中的数据类型不匹配,隐式转换在后台发生,最终导致比较因空格而失败。
在=
内使用Like
代替imageFileNameFromBookPage
来快速修复它
更好的是,在所有函数和视图中使用正确的数据类型以避免任何转换。