Member 13011316 Ответов: 1

Как хранить более 8000 символов и назначать большие сцепленные строки в SQL server 2008?


Я пытаюсь объединить большое количество идентификаторов и обновить статус всех идентификаторов. Например: aclid in (4604019,4604018,4604017,4604016,4604015,4604014,4604013,4604012,4604011,4604010,4604009,4604008,4604007,4604006,4604005,4604004,4604003,4604002,4604001,4604000,4603999,4603998,4603997,4603996,4603995,4603994,4603993,4603992,4603991,4603990,4603989,4603988)


Please check my stored Procedure:
ALTER PROCEDURE [dbo].[VT_ACLReportChangeStatus]
(
    @ChangeStatus nvarchar(50)=null,
    @ACLId nvarchar(max)
    )
AS
/* Exec VT_ACLReportChangeStatus 'Complete','4599473,4599472,4599471,4599469,4599468' */
BEGIN 

UPDATE VT_ACLReport SET Status = @ChangeStatus WHERE ACLId in (Select * from SplitDelimiterString(@ACLId,','))

End


Please check my code behind:
In code i am getting all the id's may be more than 2000-3000, but it is updating only 1000 rows..how can i increase nvarchar(max) size , to take all id's.


   ACLId = ACLId.ToString().Trim(',');
                using (SqlConnection con = new SqlConnection(cs))
                {
                    cmd = new SqlCommand("VT_ACLReportChangeStatus", con);
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
                    cmd.CommandTimeout = 3600;
                    cmd.Parameters.Add(new SqlParameter("@ACLId", SqlDbType.NVarChar,-1));
                    cmd.Parameters.Add(new SqlParameter("@ChangeStatus", SqlDbType.NVarChar, 50));
                    cmd.Parameters["@ACLId"].Value = ACLId;
                    cmd.Parameters["@ChangeStatus"].Value = ddlChangeStatus.SelectedItem.Text.ToString();
                    con.Open();
                    cmd.ExecuteNonQuery();
                    con.Close();
    }



Я пытаюсь объединить большое количество идентификаторов и обновить статус всех идентификаторов. Например: aclid in (4604019,4604018,4604017,4604016,4604015,4604014,4604013,4604012,4604011,4604010,4604009,4604008,4604007,4604006,4604005,4604004,4604003,4604002,4604001,4604000,4603999,4603998,4603997,4603996,4603995,4603994,4603993,4603992,4603991,4603990,4603989,4603988)


Тип AclId столбец имеет тип данных bigint-это личность.

Пожалуйста, не могли бы вы помочь мне в объединении большой строки и обновлении всех строк, чей aclid присутствует.

Согласно моему требованию , я должен обновить статус выбранных идентификаторов в той же таблице . поэтому я объединил все выбранные идентификаторы, а затем попытался обновить строки за один раз. но проблема возникает, если более 8000 символов, это не занимает больше 8000 символов в хранимой процедуре

Что я уже пробовал:

Please check my stored Procedure:
ALTER PROCEDURE [dbo].[VT_ACLReportChangeStatus]
(
    @ChangeStatus nvarchar(50)=null,
    @ACLId nvarchar(max)
    )
AS
/* Exec VT_ACLReportChangeStatus 'Complete','4599473,4599472,4599471,4599469,4599468' */
BEGIN 

UPDATE VT_ACLReport SET Status = @ChangeStatus WHERE ACLId in (Select * from SplitDelimiterString(@ACLId,','))

End


Please check my code behind:
In code i am getting all the id's may be more than 2000-3000, but it is updating only 1000 rows..how can i increase nvarchar(max) size , to take all id's.


   ACLId = ACLId.ToString().Trim(',');
                using (SqlConnection con = new SqlConnection(cs))
                {
                    cmd = new SqlCommand("VT_ACLReportChangeStatus", con);
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
                    cmd.CommandTimeout = 3600;
                    cmd.Parameters.Add(new SqlParameter("@ACLId", SqlDbType.NVarChar,-1));
                    cmd.Parameters.Add(new SqlParameter("@ChangeStatus", SqlDbType.NVarChar, 50));
                    cmd.Parameters["@ACLId"].Value = ACLId;
                    cmd.Parameters["@ChangeStatus"].Value = ddlChangeStatus.SelectedItem.Text.ToString();
                    con.Open();
                    cmd.ExecuteNonQuery();
                    con.Close();
    }

Mehdi Gholam

Пакет документов

Member 13011316

Не могли бы вы помочь мне с более подробной информацией? как я могу паковать все идентификаторы

F-ES Sitecore

Объединенные идентификаторы-это не очень хорошее решение, это создаст всевозможные проблемы. Вместо этого используйте таблицы parent\child (также называемые one-to-many) и храните каждый идентификатор в отдельной строке дочерней таблицы. Это позволит вам делать такие вещи, как присоединение к идентификаторам и так далее.

Jörgen Andersson

Вы должны серьезно пересмотреть свое решение, оно не нормализовано, и это только первая проблема, с которой вы столкнетесь.
Следуйте совету F-ES Sitecores.

1 Ответов

Рейтинг:
2

James Jensen

Возможно, лучший способ сделать это в SQL Server 2008-использовать пользовательскую табличную переменную для хранения коллекции значений идентификаторов, а не объединять их. Когда вы делаете это, вы можете отправить IEnumerable, содержащий идентификационные номера, на SQL Server, и вы, как правило, можете захватить и отправить столько, сколько вам нужно. Например:

Определяемая Пользователем Табличная Переменная:
------------------------------

CREATE TYPE [dbo].[MyIDType] AS TABLE(
    id int,
    status varchar(10)
)


Хранимая процедура, принимающая UDT (только один возможный метод):
-------------------------------
CREATE PROCEDURE [dbo].[VT_ACLReportChangeStatus] (
    @idlist MyIDType READONLY
)
AS
BEGIN
    ;
    MERGE dbo.VT_ACLReportChangeStatus dst
    USING @idlist src
    ON src.id = dst.id
    WHEN MATCHED THEN
        UPDATE SET
            dst.status = src.status
    ;
END
GO


Затем в коде можно создать список, заполнить его значениями идентификаторов и статусов и передать его в качестве параметра. Например (не проверено, просто с верхней части моей головы) связанная запись "строки" может быть:
public class MyStatusRecord {
    public int id { get; set; }
    public string status { get; set; }
}


Строки должны находиться в коллекции, определяющей SqlMetaData. Это обеспечивает надлежащее интерфейса и ввода, чтобы отправить объект IEnumerable хранимой proc как определяемого пользователем типа:
public class MyStatusCollection : List<MyStatusRecord>, IEnumerable<SqlDataRecord> {
    IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator() {
        var data = new SqlDataRecord(
            new SqlMetaData("id", SqlDbType.Int),
            new SqlMetaData("status", SqlDbType.VarChar, 10)
        );
        foreach (var row in this) {
            data.SetInt32(0, row.id);
            data.SetString(1, row.status);

            yield return data;
        }
    }
}


Затем вы можете создать список значений, что-то вроде:
MyStatusCollection mylist = new MyStatusCollection {
    new MyStatusRecord { id = 1, status = "changed" },
    new MyStatusRecord { id = 2, status = "deleted" },
// -- and so forth --
}


Затем вы можете отправить это в базу данных вот так:
private void UpsertData()
{
    using (var conn = Connections.GetConnection()) // -- or however you get a connection
    {
        using (var cmd = new SqlCommand("VT_ACLReportChangeStatus", conn))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@idlist", SqlDbType.Structured)
            {
                TypeName = "dbo.MyIDType",
                Value = mylist
            });
            conn.Open();
            cmd.ExecuteNonQuery();
        }
    }
}


Всю необходимую информацию можно почерпнуть из страниц MSDN sql server в интернете, поэтому не просто копируйте то, что я создал здесь...посмотрите и разберитесь в этом.

Удачи вам! :)