我需要將xml發送到存儲過程。在XML會是什麼樣子從xml生成動態where子句
<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>
- SearchField標籤保持在其搜索將發生
- FilterCondition中的標籤將持有我用它來搜索和比較像'%「< =」'運營商的搜索字段名稱< =」等 我們將搜索
- MatchCase
- ConditionData標籤將實際值表明它會區分大小寫或不
我可以加載xml並在遊標的while循環中迭代並生成where子句。我的問題是我如何生成基於字段數據類型的where子句。
如果字段是字符串,則我們總是比較喜歡用「」單引號 如果字段爲數字或位類型,那麼我們就可以,如果該字段爲日期時間的話,我喜歡比較喜歡 沒有單引號 比較convert(@dob,varchar,112) > '20100101'
所以我的問題是如何根據數據類型生成where子句。 我需要動態獲取字段數據類型,並據此構建where子句。 請分享最好的想法。謝謝
我改變我的xml位。我包括每個領域的表名。所以請告訴我,我需要在這個SQL中更改以顯示每個字段的數據類型。顯示我需要加入系統表的數據類型。所以請在ur sql中做必要的更改以便與sys表聯接以獲取&顯示每個字段的數據類型。
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)[email protected]+space(1)[email protected]
END
ELSE IF CHARINDEX('NUMERIC', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)[email protected]+space(1)[email protected]
END
ELSE IF CHARINDEX('BIT', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)[email protected]+space(1)[email protected]
END
ELSE IF CHARINDEX('DECIMAL', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)[email protected]+space(1)[email protected]
END
ELSE IF CHARINDEX('FLOAT', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)[email protected]+space(1)[email protected]
END
ELSE IF CHARINDEX('REAL', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)[email protected]+space(1)[email protected]
END
ELSE IF CHARINDEX('MONEY', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)[email protected]+space(1)[email protected]
END
ELSE IF CHARINDEX('DATE', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + 'CONVERT(varchar,'[email protected]+',112)' + space(1)[email protected]+'CONVERT(varchar,'''[email protected]+''',112)'
END
ELSE IF CHARINDEX('CHAR', UPPER(@ColumnType)) > 0
BEGIN
SET @WhereClause = @WhereClause + space(1)+ @LogicalOperator + space(1) + @SearchField + space(1)[email protected]+''''[email protected]+''''
END
FETCH NEXT FROM SearchCursor
INTO @SearchField, @Operator,@ConditionData,@MatchCase,@TableName,@Validity,@ColumnType,@ColumnPrecision,@ColumnScale,@ColumnNullable
END
CLOSE SearchCursor
DEALLOCATE SearchCursor
SELECT @WhereClause
END
您確定要在SQL中執行此操作嗎?如果你在調用SQL的代碼中這樣做會更好嗎?該代碼的語言是什麼? – svick 2012-01-03 15:01:33
嗨托馬斯道歉,我的答覆很慢。你的解決方案對我來說很好。我認爲這只是一個報告構造函數,因此構建查詢的性能並不是一個優先事項。我不會喋喋不休地介紹遊標的使用等。我能發現的唯一可能會導致你問題的是你傳入你的字符串的@ConditionData var,如果它包含一個單引號的字符串,你的結果查詢將會出現語法錯誤 - 您可能想要將其轉義。 – HeavenCore 2012-01-04 22:10:27
謝謝指出好東西。所以我會用@ConditionData中的雙引號替換單引號,如 REPLACE(@ConditionData,'''','''''')。任何其他建議 – Thomas 2012-01-05 07:07:43