使用用户定义的表在列名之间进行迭代

时间:2019-01-03 17:31:16

标签: c# sql-server tsql

我目前正在使用c#和sql服务器管理工​​作室:

我有一个像这样的表

+--------+-------------+-------------+------+
| TaskId | Item2(bool) | Item3(bool) | etc… |
+--------+-------------+-------------+------+

我不知道bool列名,因为它们是通过代码(用户创建它们)创建的。

好吧,我在窗体打开时插入数据,使用TaskId和所有boolsDEFAULT(0),因为我有类似的东西:

+--------------------------------------+-------------+-------------+------+
|                TaskId                | Item2(bool) | Item3(bool) | etc… |
+--------------------------------------+-------------+-------------+------+
| 9B093907-2072-4F59-A55C-0003CE89EF9E |           0 |           0 |    0 |
+--------------------------------------+-------------+-------------+------+

我想更新布尔值,因此在C#中我创建了数据表以使用User-defined tables

 DataTable checkboxList = new DataTable();
            var checkboxNameColumn = checkboxList.Columns.Add("CheckBoxName", typeof(string));
            var checkBoxValueColumns = checkboxList.Columns.Add("CheckBoxValue", typeof(bool));

            foreach (var c in checkBoxes)
            {
                var row = checkboxList.NewRow();
                row[checkboxNameColumn] = c.Name;
                row[checkBoxValueColumns] = c.Checked;
                checkboxList.Rows.Add(row);
            }


            Guid currentUser = new Guid(EBResources.EmpGuid);
            Guid currentTaskId = new Guid(TaskId);
            db.ExeSQLRedMarkItems($"usp_RedMarkItem_Insert", checkboxList, "@CheckBoxList", currentTaskId, currentUser);

CheckBoxName等于我的列名,CheckBoxValue是该列的值。所以我的Datatable是正确的,现在我将其发送给sql:

用户定义表

CREATE TYPE [HELPER].CheckBoxValues AS TABLE(
CheckBoxName VARCHAR(255) NOT NULL,
CheckBoxValue BIT NOT NULL )

存储过程:

CREATE OR ALTER PROCEDURE [dbo].[usp_RedMarkItem_Insert]
             -- Add the parameters for the stored procedure here
             @TaskId       UNIQUEIDENTIFIER
            , @CheckBoxList [Helper].[CheckBoxValues] READONLY
            , @CurrentUser  UNIQUEIDENTIFIER
AS
        BEGIN
            -- SET NOCOUNT ON added to prevent extra result sets from
            -- interfering with SELECT statements.
            SET NOCOUNT ON;

   DECLARE @CurrentCheckboxName VARCHAR(255) = (SELECT
                                                        [CheckBoxName]
                                                        FROM @CheckBoxList)

               UPDATE [m]
                SET
                    @CurrentCheckboxName = [c].[CheckBoxValue]
                    FROM [RedMarkItems] [m]
                        JOIN @CheckBoxList [c] ON [c].[CheckBoxName] = @CurrentCheckboxName
                        WHERE m.TaskId = @TaskId
            END

如您所见,我声明了@CurrentCheckboxName,但由于选择返回多个值,因此抛出了错误:

  

子查询返回了多个值。当   子查询遵循=,!=,<,<=,>,> =,或当子查询用作   表达式。

我需要做些什么来在列名之间进行迭代?问候

2 个答案:

答案 0 :(得分:0)

您不需要下面的行

  DECLARE @CurrentCheckboxName VARCHAR(255) = (SELECT
                                                    [CheckBoxName]
                                                    FROM @CheckBoxList)

您已经在@CheckBoxList中拥有了它。您需要以下类似的内容

 UPDATE [m]
 SET m.val = [c].Val
 JOIN @CheckBoxList [c] 
     ON [c].[CheckBoxName] = m.CheckBoxName
 WHERE m.TaskId = @TaskId

您可以从Information_schema获取列名

SELECT
  TABLE_NAME,
  COLUMN_NAME
FROM
  INFORMATION_SCHEMA.COLUMNS

答案 1 :(得分:0)

您的数据库设计将给您带来很多问题。 SQL Server最适合使用具有指定数量的命名列的预定义表:虽然可以将系统设置为具有用户定义的字段标签,但是从某种意义上说,具有实际的用户定义的 fields 创建在数据库之上运行的数据库。要使用和管理这些基础结构,您将需要大量尚未创建的基础结构。

我的建议:如果您需要一行包含用户定义的布尔值的集合,请将布尔值存储为XML。

CREATE TABLE dbo.Task
(
   TaskId int,
   Checkboxes xml
)

您的XML将被定义为这样(尽管您可以通过多种方法来定义它!)

 <Checkboxes>
   <Checkbox name="User-defined name" value="True" />
   <Checkbox name="Some other name" value="False" />
 </Checkboxes>

您仍然会遇到一些挑战-例如,如果要提取所有具有复选框“ Apple”且值为true的行-但您的行数会少于您将使用实际的用户定义表。

实际上,以一种有用的方式查询XML是可能的。