Reputation: 34188
i need to send a xml to a store procedure. the xml would look like
<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>
i can load the xml and iterate in while loop of cursor and generate a where clause. my question is how can i generate where clause based on field data type.
if the field is string then we always compare like with in '' single quote
if the field is numeric or bit type then we can compare without single quote
if the field is date time then i like to compare like
convert(@dob,varchar,112) > '20100101'
so my question is how to generate where clause based on data type. i need to fetch the field data type dynamically and accordingly build the where clause. please share the best idea. thanks
i change my xml bit. i include table name for every field. so please tell me what i need to change in this sql to show the data type for every field. to show the data type i need to join with system table. so please do necessary change in ur sql for join with sys table to fetch & show the data type for each field.
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)
here is my solution.
/*
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
Upvotes: 0
Views: 900
Reputation: 7683
2 small things, 1 < & > etc are very illegal in XML markup, if you want to reliably parse it, whatever is generating the XML will need to encode these to the approriate entity reference:
< < less than
> > greater than
& & ampersand
' ' apostrophe
" " quotation mark
Also, your closing nodes and opening nodes have a typo, for instance <param> is closed by <params> (note the 'S') - assuming this is a typo.
That said, the hardest part is parsing the XML into usefull data that you can use to build your dynamic SQL. You could do this by parsing the XML into a table:
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
Once you have the parsed data, its just an easy case (if not tedious) of iterating through the table and building the where clase string - let me know if you need assistance with that part.
Upvotes: 1