我需要将xml发送到商店程序。 xml看起来像
<NewDataSet>
<param>
<SearchField>EmployeeID</SearchField>
<FilterCondition> >= </FilterCondition>
<ConditionData>201</ConditionData>
<MatchCase>0</MatchCase>
</params>
<param>
<SearchField>DeptID</SearchField>
<FilterCondition> = </FilterCondition>
<ConditionData>AC01</ConditionData>
<MatchCase>0</MatchCase>
</params>
<param>
<SearchField>Dob</SearchField>
<FilterCondition> <= </FilterCondition>
<ConditionData>23-MAR-2010</ConditionData>
<MatchCase>0</MatchCase>
</params>
</NewDataSet>
我可以加载xml并迭代while循环游标并生成where子句。我的问题是如何根据字段数据类型生成where子句。
如果字段是字符串,那么我们总是在''单引号中进行比较
如果字段是数字或位类型,那么我们可以比较没有单引号
如果该字段是日期时间,那么我想比较喜欢
convert(@dob,varchar,112) > '20100101'
所以我的问题是如何基于数据类型生成where子句。 我需要动态获取字段数据类型,并相应地构建where子句。 请分享最好的主意。感谢
我改变了我的xml位。我为每个字段都包含表名。所以请告诉我在这个sql中需要更改的内容,以显示每个字段的数据类型。显示我需要加入系统表的数据类型。所以请在你的sql中进行必要的更改,以便与sys table一起加入fetch&amp;显示每个字段的数据类型。
INSERT INTO @tbl_WhereClause (SearchField, Operator, ConditionData, MatchCase,TableName)
SELECT A.B.value('(SearchField)[1]', 'VARCHAR(255)' ) SearchField,
A.B.value('(FilterCondition)[1]', 'VARCHAR(25)' ) Operator,
A.B.value('(ConditionData)[1]', 'VARCHAR(MAX)' ) ConditionData,
A.B.value('(MatchCase)[1]', 'BIT' ) MatchCase,
A.B.value('(Table)[1]', 'VARCHAR(MAX)' ) TableName
FROM @WhereClause_XML.nodes('/NewDataSet/param') A(B)
这是我的解决方案。
/*
XML DATA SAMPLE
<NewDataSet>
<param>
<SearchField>EmpID</SearchField>
<FilterCondition> >= </FilterCondition>
<ConditionData>201</ConditionData>
<MatchCase>0</MatchCase>
<Table>Employee</Table>
</param>
<param>
<SearchField>DeptName</SearchField>
<FilterCondition> = </FilterCondition>
<ConditionData>AC01</ConditionData>
<MatchCase>1</MatchCase>
<Table>Department</Table>
</param>
<param>
<SearchField>Dob</SearchField>
<FilterCondition> >= </FilterCondition>
<ConditionData>20120104</ConditionData>
<MatchCase>0</MatchCase>
<Table>Employee</Table>
</param>
</NewDataSet>'
*/
CREATE PROCEDURE GenericSearch
(
@WhereClause_XML XML,
@LogicalOperator VARCHAR(3)
)
AS
BEGIN
DECLARE @SearchField VARCHAR(255),
@Operator VARCHAR(25),
@ConditionData VARCHAR(MAX),
@MatchCase BIT,
@TableName VARCHAR(MAX),
@Validity VARCHAR(100),
@ColumnType VARCHAR(128),
@ColumnPrecision INT,
@ColumnScale INT,
@ColumnNullable bit,
@WhereClause VARCHAR(MAX)
DECLARE @tbl_WhereClause AS TABLE
(
SearchField VARCHAR(255),
Operator VARCHAR(25),
ConditionData VARCHAR(MAX),
MatchCase BIT,
TableName VARCHAR(MAX),
Validity VARCHAR(100),
ColumnType VARCHAR(128),
ColumnPrecision INT,
ColumnScale INT,
ColumnNullable bit
)
INSERT INTO @tbl_WhereClause (SearchField, Operator, ConditionData, MatchCase,TableName,
Validity, ColumnType, ColumnPrecision, ColumnScale, ColumnNullable)
SELECT A.B.value('(SearchField)[1]', 'VARCHAR(255)' ) SearchField,
A.B.value('(FilterCondition)[1]', 'VARCHAR(25)' ) Operator,
A.B.value('(ConditionData)[1]', 'VARCHAR(MAX)' ) ConditionData,
A.B.value('(MatchCase)[1]', 'BIT' ) MatchCase,
A.B.value('(Table)[1]', 'VARCHAR(MAX)' ) TableName,
CASE WHEN t.NAME+c.NAME IS NULL THEN 'invalid' ELSE 'valid' END ,
ty.NAME,
c.PRECISION,
c.Scale,
c.Is_Nullable
FROM @WhereClause_XML.nodes('/NewDataSet/param') A(B)
LEFT JOIN sys.tables t ON t.name = A.B.value('(Table)[1]', 'VARCHAR(MAX)' )
LEFT JOIN sys.COLUMNS c ON T.OBJECT_ID = c.OBJECT_ID AND c.name = A.B.value('(SearchField)[1]', 'VARCHAR(255)' )
LEFT JOIN sys.types ty ON c.system_type_id = ty.system_type_id
--SELECT * FROM @tbl_WhereClause
SET @WhereClause= 'WHERE 1=1'
DECLARE SearchCursor CURSOR FOR
SELECT * FROM @tbl_WhereClause
OPEN SearchCursor
FETCH NEXT FROM SearchCursor
INTO @SearchField, @Operator,@ConditionData,@MatchCase,@TableName,@Validity,@ColumnType,@ColumnPrecision,@Colu mnScale,@ColumnNullable
WHILE @@FETCH_STATUS = 0
BEGIN
IF CHARINDEX('INT', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)+@Operator+space(1)+@ConditionData
END
ELSE IF CHARINDEX('NUMERIC', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)+@Operator+space(1)+@ConditionData
END
ELSE IF CHARINDEX('BIT', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)+@Operator+space(1)+@ConditionData
END
ELSE IF CHARINDEX('DECIMAL', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)+@Operator+space(1)+@ConditionData
END
ELSE IF CHARINDEX('FLOAT', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)+@Operator+space(1)+@ConditionData
END
ELSE IF CHARINDEX('REAL', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)+@Operator+space(1)+@ConditionData
END
ELSE IF CHARINDEX('MONEY', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)+@Operator+space(1)+@ConditionData
END
ELSE IF CHARINDEX('DATE', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + 'CONVERT(varchar,'+@SearchField+',112)' + space(1)+@Operator+'CONVERT(varchar,'''+@ConditionData+''',112)'
END
ELSE IF CHARINDEX('CHAR', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)+@Operator+''''+@ConditionData+''''
END
FETCH NEXT FROM SearchCursor
INTO @SearchField, @Operator,@ConditionData,@MatchCase,@TableName,@Validity,@ColumnType,@ColumnPrecision,@ColumnScale,@ColumnNullable
END
CLOSE SearchCursor
DEALLOCATE SearchCursor
SELECT @WhereClause
END
答案 0 :(得分:1)
2个小东西,1&lt; &安培; &GT;在XML标记中是非常非法的,如果你想要可靠地解析它,生成XML需要将这些编码到approriate实体引用:
< < less than
> > greater than
& & ampersand
' ' apostrophe
" " quotation mark
此外,您的结束节点和开放节点有一个拼写错误,例如&lt; param&gt;被&lt; params&gt;关闭(注意'S') - 假设这是一个错字。
尽管如此,最难的部分是将XML解析为可用于构建动态SQL的有用数据。您可以通过将XML解析为表来执行此操作:
DECLARE @tbl_WhereClause AS TABLE (
SearchField VARCHAR(255),
Operator VARCHAR(25),
ConditionData VARCHAR(MAX),
MatchCase BIT
)
DECLARE @WhereClause_XML XML
SET @WhereClause_XML = '
<NewDataSet>
<param>
<SearchField>EmployeeID</SearchField>
<FilterCondition> >= </FilterCondition>
<ConditionData>201</ConditionData>
<MatchCase>0</MatchCase>
</param>
<param>
<SearchField>DeptID</SearchField>
<FilterCondition> = </FilterCondition>
<ConditionData>AC01</ConditionData>
<MatchCase>0</MatchCase>
</param>
<param>
<SearchField>Dob</SearchField>
<FilterCondition> <= </FilterCondition>
<ConditionData>23-MAR-2010</ConditionData>
<MatchCase>0</MatchCase>
</param>
</NewDataSet>'
INSERT INTO @tbl_WhereClause (SearchField, Operator, ConditionData, MatchCase)
SELECT A.B.value('(SearchField)[1]', 'VARCHAR(255)' ) SearchField,
A.B.value('(FilterCondition)[1]', 'VARCHAR(25)' ) Operator,
A.B.value('(ConditionData)[1]', 'VARCHAR(MAX)' ) ConditionData,
A.B.value('(MatchCase)[1]', 'BIT' ) ConditionData
FROM @WhereClause_XML.nodes('/NewDataSet/param') A(B)
SELECT * FROM @tbl_WhereClause
一旦你获得了解析数据,它只是一个简单的案例(如果不是单调乏味)迭代表格并构建where clase字符串 - 如果你需要这方面的帮助,请告诉我。