将查询的值存储到 SQL 服务器变量中
Store the value of a query into a SQL Server variable
代码的 objective 是 运行 动态查询和 return 0(如果列中没有包含数据的行)和 return 1如果列中有包含数据的行。这是我的存储过程代码:
ALTER proc [dbo].[usp_ColumnFieldValidator]
(
@TblName nvarchar(30),
@ColumnName nvarchar(30),
@RetVal bit output
)
as
begin
declare @CountOfRowsQuery as nvarchar(300)
set @CountOfRowsQuery = 'select count('+quotename(@ColumnName)+') from '+quotename(@TblName)+' having count(' +quotename(@ColumnName)+') = nullif(count('+quotename(@ColumnName)+'),0)'
execute sp_executesql @CountOfRowsQuery
select @RetVal = dbo.fn_ColumnValidator(@CountOfRowsQuery)
end
如您所见,正在调用用户定义的函数来设置@RetVal 的值。这是我的用户定义函数代码。
ALTER function [dbo].[fn_ColumnValidator]
(
@NullChecker as nvarchar(max)
)
returns bit
as
begin
declare @returnVar as bit
if @NullChecker is null
set @returnVar = 0
else
set @returnVar = 1
return @returnVar
end
@RetVal 的输出始终为 1,我将此错误归因于@CountOfRowsQuery 存储了整个字符串而不是查询的值,即:如果行数为零,@CountOfRowsQuery = null 否则,@CountOfRowsQuery = 列中存在的行数。为了让事情更清楚,我附上了 运行 程序时的输出截图。
- Output of a table that contains rows with data
- Output of a table that contains no rows with no data
如您在列表项 2 中所见,sp return 为空,但 function_returned_value 被设置为 1 而不是 0。
The objective of the code is to run a query dynamically and return 0 if there are no rows with data present in the columns and to return 1 if there are rows with data in the columns.
伙计,如果这不是 over-complication 我不知道是什么。
这是一个更简单(也更有效)的查询:
SELECT CAST(IIF(EXISTS(
SELECT 1
FROM TableName
WHERE ColumnName IS NOT NULL
), 1, 0) As Bit)
现在,要将其更改为使用动态 SQL 且不会让您暴露于 SQL 注入威胁的过程,您可以这样做:
ALTER PROCEDURE [dbo].[usp_ColumnFieldValidator]
(
@TblName sysname,
@ColumnName sysname,
@RetVal bit output
)
AS
BEGIN
IF NOT EXISTS(
SELECT 1
FROM Information_Schema.Columns
WHERE Table_Name = @TblName
AND Column_Name = @ColumnName
)
RETURN;
DECLARE @Sql nvarchar(1000) =
N'SELECT @RetVal = CAST(IIF(EXISTS(
SELECT 1
FROM '+ QUOTENAME(@TblName) + N'
WHERE '+ QUOTENAME(@ColumnName) + N' IS NOT NULL
), 1, 0) As Bit)'
EXEC sp_executesql @Sql, N'@RetVal bit output', @RetVal OUTPUT;
END
要点:
我已经将 @TblName
和 @ColumnName
变量更改为数据类型 sysname
而不是原来的 nvarchar(30)
- 因为那是数据类型 SQL 服务器内部用于存储标识符。
因为标识符不能被参数化,所以我 white-listed 它们。
我正在使用 sp_executeSql
将动态查询的值直接返回到我的输出参数中。
有关动态 SQL 的更多提示和技巧,您可以阅读我的博客 post 标题为 The do’s and don’ts of dynamic SQL for SQL Server
代码的 objective 是 运行 动态查询和 return 0(如果列中没有包含数据的行)和 return 1如果列中有包含数据的行。这是我的存储过程代码:
ALTER proc [dbo].[usp_ColumnFieldValidator]
(
@TblName nvarchar(30),
@ColumnName nvarchar(30),
@RetVal bit output
)
as
begin
declare @CountOfRowsQuery as nvarchar(300)
set @CountOfRowsQuery = 'select count('+quotename(@ColumnName)+') from '+quotename(@TblName)+' having count(' +quotename(@ColumnName)+') = nullif(count('+quotename(@ColumnName)+'),0)'
execute sp_executesql @CountOfRowsQuery
select @RetVal = dbo.fn_ColumnValidator(@CountOfRowsQuery)
end
如您所见,正在调用用户定义的函数来设置@RetVal 的值。这是我的用户定义函数代码。
ALTER function [dbo].[fn_ColumnValidator]
(
@NullChecker as nvarchar(max)
)
returns bit
as
begin
declare @returnVar as bit
if @NullChecker is null
set @returnVar = 0
else
set @returnVar = 1
return @returnVar
end
@RetVal 的输出始终为 1,我将此错误归因于@CountOfRowsQuery 存储了整个字符串而不是查询的值,即:如果行数为零,@CountOfRowsQuery = null 否则,@CountOfRowsQuery = 列中存在的行数。为了让事情更清楚,我附上了 运行 程序时的输出截图。
- Output of a table that contains rows with data
- Output of a table that contains no rows with no data
如您在列表项 2 中所见,sp return 为空,但 function_returned_value 被设置为 1 而不是 0。
The objective of the code is to run a query dynamically and return 0 if there are no rows with data present in the columns and to return 1 if there are rows with data in the columns.
伙计,如果这不是 over-complication 我不知道是什么。
这是一个更简单(也更有效)的查询:
SELECT CAST(IIF(EXISTS(
SELECT 1
FROM TableName
WHERE ColumnName IS NOT NULL
), 1, 0) As Bit)
现在,要将其更改为使用动态 SQL 且不会让您暴露于 SQL 注入威胁的过程,您可以这样做:
ALTER PROCEDURE [dbo].[usp_ColumnFieldValidator]
(
@TblName sysname,
@ColumnName sysname,
@RetVal bit output
)
AS
BEGIN
IF NOT EXISTS(
SELECT 1
FROM Information_Schema.Columns
WHERE Table_Name = @TblName
AND Column_Name = @ColumnName
)
RETURN;
DECLARE @Sql nvarchar(1000) =
N'SELECT @RetVal = CAST(IIF(EXISTS(
SELECT 1
FROM '+ QUOTENAME(@TblName) + N'
WHERE '+ QUOTENAME(@ColumnName) + N' IS NOT NULL
), 1, 0) As Bit)'
EXEC sp_executesql @Sql, N'@RetVal bit output', @RetVal OUTPUT;
END
要点:
我已经将
@TblName
和@ColumnName
变量更改为数据类型sysname
而不是原来的nvarchar(30)
- 因为那是数据类型 SQL 服务器内部用于存储标识符。因为标识符不能被参数化,所以我 white-listed 它们。
我正在使用
sp_executeSql
将动态查询的值直接返回到我的输出参数中。
有关动态 SQL 的更多提示和技巧,您可以阅读我的博客 post 标题为 The do’s and don’ts of dynamic SQL for SQL Server