在 IN 之后使用 IIF() 和查询 where 子句中的宏替换变量

问题描述 投票:0回答:2

我正在尝试完成这样的查询:

select  *
    from table1
    where id1 in IIF(llchoose_flag = .T., (&lcid_list.), (id1))

其中字符串 lcid_list = "1,2,3".

所以如果 llchoose_flag = .T.,我想选择 id1 在变量 lcid_list 定义的列表中的记录。如果 llchoose_flag = .F.,我想选择所有记录,即 (id1) 中的 id1。 我也尝试过使用 INLIST() 但两种方法都没有成功。 我似乎不断收到的错误是:函数名称丢失),但我不相信这是真的。我开始认为可能无法在 IN 子句中使用 IIF() 语句,但也许我只需要修复我的语法。

我正在尝试在 FoxPro 或 SQL 中完成此查询。上面的代码语法是我在 FoxPro 中的尝试,但在 SQL 中它会非常相似,除了我相信的宏替换符号?

我能够运行 FoxPro 查询,例如:

select  *
    from table1
    where id1 in (&lcid_list.)

所以好像不喜欢IN后面的IIF()。解决此问题的一种方法是根据 llchoose_flag 在 lcid_list 变量中存储不同的值,但这将涉及在 llchoose_flag = .F 时在该字符串中存储数百万个 id 值。 (表 1 中的所有 id 记录),这不如 IIF 方法有效。

如果有人知道完成此类查询的方法,请告诉我。谢谢。

sql-server visual-foxpro foxpro
2个回答
0
投票

在VFP中基本上是:

select  * from table1 where !m.llChoose or id1 in (&lcid_list.)

在 SQL Server 中它会是相似的。

但是,如果你考虑一下,VFP 中的语句不能超过 8K,因此 id 计数最多小于 4K。如果它是对 SQL 服务器的调用,则该限制要高得多(SQL 服务器端限制要高得多),对于 VFP 端 16 Mb 的文档。

由于调用是从 VFP 内部开始的,无论是 VFP 数据还是 SQL 服务器,最好从哪里消除 if 并将其推送到外部,即:

if m.llChoose
   select  * from table1 where id1 in (&lcid_list.)
else
   select  * from table1
endif  

如果它用于 SQL 服务器,那么您可以创建一个临时表并逐个填充它,或者使用批量复制 activex(在 foxite.com 上搜索 sqlbulkcopy)。然后你只需做一个连接。

另一种方法是将参数传递给 SQL Server 并在那里进行解析。 SQL Server 本身在字符串操作上很慢,并且它可能会在处理大字符串时超时。但是,您可以使用 CLR 函数进行解析。即:在 Foxite 上检查:

SQL server 的一个小工具

使用它,你可以将你的 ID 列表作为字符串参数传递,它的长度可以达到 2 Gb(理论上,如果你使用备忘录字段作为参数源),或者 16 Mb 纯字符串内存变量.你的代码看起来像:

lcSQL = 'select * from Table1 t'
if m.llChoose 
   lcSQL = m.lcSQL + ;
      ' inner join ufn_IntsToTable(?m.lcid_list) ids'+;
      ' on t.id1 = ids.v'
endif

lcID_list = "1,2,3"

SQLExec(m.handle, m.lcSQL, 'crsResult')

PS:您还可以发送一个 XML 表并在 SQL 服务器端解析以进行连接(会更慢)。


0
投票

从 Split(@lcid_list,',') 中选择项目
项目

这是 sql server 的代码

declare  @lcid_list varchar(100)= '1,2,3'
declare  @id1 int=1
declare  @llchoose_flag varchar(100)='T'

select  *
from table1
 where 
 @llchoose_flag='f' or 
                 
    ( @llchoose_flag = 'T' and id1 in(select item from Split(@lcid_list,',')))
 or ( @llchoose_flag not in( 'F' , 'T') and id1 in(@id1))

sql server(最旧版本)中有 Split 函数,因此我们需要创建用户定义函数。

CREATE FUNCTION Split (
     @InputString                  VARCHAR(8000),
     @Delimiter                    VARCHAR(50)
)

RETURNS @Items TABLE (
     Item                          VARCHAR(8000)
)

AS
BEGIN
     IF @Delimiter = ' '
     BEGIN
           SET @Delimiter = ','
           SET @InputString = REPLACE(@InputString, ' ', @Delimiter)
     END

     IF (@Delimiter IS NULL OR @Delimiter = '')
           SET @Delimiter = ','

--INSERT INTO @Items VALUES (@Delimiter) -- Diagnostic
--INSERT INTO @Items VALUES (@InputString) -- Diagnostic

     DECLARE @Item           VARCHAR(8000)
     DECLARE @ItemList       VARCHAR(8000)
     DECLARE @DelimIndex     INT

     SET @ItemList = @InputString
     SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
     WHILE (@DelimIndex != 0)
     BEGIN
           SET @Item = SUBSTRING(@ItemList, 0, @DelimIndex)
           INSERT INTO @Items VALUES (@Item)

           -- Set @ItemList = @ItemList minus one less item
           SET @ItemList = SUBSTRING(@ItemList, @DelimIndex+1, LEN(@ItemList)-@DelimIndex)
           SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
     END -- End WHILE

     IF @Item IS NOT NULL -- At least one delimiter was encountered in @InputString
     BEGIN
           SET @Item = @ItemList
           INSERT INTO @Items VALUES (@Item)
     END

     -- No delimiters were encountered in @InputString, so just return @InputString
     ELSE INSERT INTO @Items VALUES (@InputString)

     RETURN

END -- End Function
GO

---- Set Permissions
--GRANT SELECT ON Split TO UserRole1
--GRANT SELECT ON Split TO UserRole2
--GO

您可以使用以下语句插入基础数据:

drop table   table1
create table table1(llchoose_flag varchar(100),id1 int)

insert into table1(id1 ,llchoose_flag)values(1,'f')
insert into table1(id1 ,llchoose_flag)values(3,'f')
insert into table1(id1 ,llchoose_flag)values(5,'t')
insert into table1(id1 ,llchoose_flag)values(6,'j')
© www.soinside.com 2019 - 2024. All rights reserved.