How to update my table where updated columns names stored in another table in SQL Server - sql

I have table User with n columns that stores user information in it.
I have another table User_Edit_Changes that I use to temporarily store changes to table User in it so that after admin confirmation I update the actual table User with new values.
In table User_Edit_Changes, I stored which user column requested for update and what is new value for that. How to write a dynamic query to get just changed value columns and new value from User_Edit_Changes and update the User table?
here is my sample create table command ,
teacher stores infos,
Tbl_ProfessorRequest stores edit change request,
Tbl_ProfessorEditInfoFields stores which fileds teacher request to edit
CREATE TABLE [dbo].[Teacher](
[code_ostad] [numeric](18, 0) NOT NULL,
[name] [varchar](30) NULL,
[family] [varchar](40) NOT NULL,
[namep] [varchar](30) NULL,
[idmadrak] [numeric](18, 0) NULL,
[namemadrak] [varchar](50) NULL,
[idresh] [numeric](18, 0) NULL,
[nameresh] [varchar](50) NULL,
[martabeh] [numeric](18, 0) NULL,
[namemartabeh] [varchar](30) NULL,
[nahveh_hamk] [numeric](18, 0) NULL,
CREATE TABLE [Request].[Tbl_ProfessorRequest](
[ProfessorRequestID] [int] IDENTITY(1,1) NOT NULL,
[Code_Ostad] [int] NULL,
[RequestTypeID] [bigint] NULL,
[RequestLogID] [bigint] NULL,
[CreateDate] [nvarchar](10) NULL,
[Note] [nvarchar](1000) NULL,
[term] [nvarchar](8) NULL,
[ProfessorMessage] [nvarchar](1000) NULL,
[Erae_Be] [nvarchar](100) NULL,
[ChangeSet] [int] NULL,
[isdeleted] [bit] NOT NULL,
[ScanImageUrl] [nvarchar](300) NULL,
CREATE TABLE [Request].[Tbl_ProfessorEditInfoFields](
[Id] [int] IDENTITY(1,1) NOT NULL,
[code_ostad] [int] NOT NULL,
[teacher_Column_Name] [nvarchar](200) NULL,
[OldValue] [nvarchar](200) NULL,
[NewValue] [nvarchar](200) NULL,
[State] [int] NOT NULL,
[ProfessorRequestID] [int] NOT NULL,

I'd say you have 3 options:
Handle the logic of updates outside the database, in what ever your application is built with. That's most likely the easiest way, since this kind of dynamic handling is not what databases are good at.
Build a dynamic SQL clause based on the contents of User_Edit_Changes. Loop through the changes in the table, construct an update statement into a variable and use sp_executesql to execute it. With cursor the code should be something like this:
set #params = N'#NewValue varchar(100)'
fetch next from yourcursor into #FieldName, #NewValue
while ##FETCH_STATUS = 0 begin
set #sql = 'update User set ' + #FieldName + ' = #NewValue'
exec sp_executesql #sql, #params, #NewValue = #NewValue
fetch next from yourcursor into #FieldName, #NewValue
end
Create static SQL statements for updating each of the columns. You can build something like this:
update U
set U.UserName = C.NewValue
from
User U
join User_Edit_Changes C on U.UserId = C.UserId
where
C.FieldName = 'UserName'
For this you of course need to have similar statements for each of your columns. You could build one massive update query with pivot or max+case, but handling the old and new values gets pretty complex.

Related

Query Failed to Join two tables records into gridview

I am trying to join two tables by using SQL query by using single parameters. I have two tables student and student job record and I want to join this two table into single a single based on ID.
Student profile table.
CREATE TABLE [dbo].[Student_Profile]
(
[StudentID] [int] IDENTITY(1,1) NOT NULL,
[First_Name] [varchar](50) NULL,
[Last_Name] [varchar](50) NULL,
[Email] [varchar](500) NULL,
[Qualifactions] [varchar](50) NULL,
[Name_Of_Instatutions] [varchar](50) NULL,
[City] [varchar](50) NULL,
[Country] [varchar](50) NULL,
[Contract] [varchar](50) NULL
) ON [PRIMARY]
Here is the student job profile table.
CREATE TABLE [dbo].[Student_Job_Record]
(
[Record_ID] [int] IDENTITY(1,1) NOT NULL,
[StudentID] [int] NULL,
[Total_Hours_Work] [varchar](50) NULL,
[Pay_Rate] [varchar](50) NULL,
[Total_Amount_Paid] [varchar](500) NULL
) ON [PRIMARY]
I am using a stored procedure to display the data into gridview. Here is the stored procedure code.
CREATE PROCEDURE [dbo].[spGetStudentsDeatilsByID]
#ID int
AS
BEGIN
SELECT
Student_Profile.First_Name, Student_Profile.Last_Name,
Job_Profile.Title, Job_Profile.Location,
Job_Profile.Type_Contract, Job_Profile.Salary
FROM
Student_Profile, Job_Profile
WHERE
Student_Profile.StudentID = #ID
AND Job_Profile.StudentID = #ID
END
I want to display and join this two table into gridview based on studentID. But when I enter the student Id and click the submit button, nothing is displayed.
Here is the screen shot when I run the applications.
Try the following. If you do not have StudentID in Job_Profile then you can use LEFT JOIN.
Create proc [dbo].[spGetStudentsDeatilsByID]
#ID int
as
Begin
SELECT
sp.First_Name,
sp.Last_Name ,
jp.Title,
jp.Location,
jp.Type_Contract,
jp.Salary
FROM Student_Profile sp
LEFT JOIN Job_Profile jp
ON sp.StudentID = jp.StudentID
WHERE sp.StudentID =#ID
End
GO

SQL Server export image to hardisc by iterating through fieldnames

We receive 10 images in varchar format through a mobile device app which are stored in one record of a table. The fields where the images are imported are named ImportPictureData, ImportPictureData2,...
[ID] [int] IDENTITY(1,1) NOT NULL,
[Projectnumber] [varchar](20) NULL,
[DeviceID] [nchar](20) NULL,
[Sendtime] [datetime] NULL,
[DeviceName] [nchar](30) NULL,
[ImportPictureData] [varchar](max) NULL,
[PictureData] [varbinary](max) NULL,
[ImportPictureData2] [varchar](max) NULL,
[PictureData2] [varbinary](max) NULL,
[ImportPictureData3] [varchar](max) NULL,
[PictureData3] [varbinary](max) NULL,
[ImportPictureData4] [varchar](max) NULL,
[PictureData4] [varbinary](max) NULL,
[ImportPictureData5] [varchar](max) NULL,
[PictureData5] [varbinary](max) NULL,
[ImportPictureData6] [varchar](max) NULL,
[PictureData6] [varbinary](max) NULL,
[ImportPictureData7] [varchar](max) NULL,
[PictureData7] [varbinary](max) NULL,
[ImportPictureData8] [varchar](max) NULL,
[PictureData8] [varbinary](max) NULL,
[ImportPictureData9] [varchar](max) NULL,
[PictureData9] [varbinary](max) NULL,
more of the importfields could be added.
To make the export flexible, I read the fieldnames in a table variable and try to create a dynamic SQL for the loop through the fields.
The SQL-string looks good where I create the string and print it(!) and then I try to assign the string to the variable which should recieve the image data:
set #sqlDynamicString='(Select Cast('''' AS XML).value(''xs:base64Binary(sql:column("'+ #PictureDateFieldName + '"))'', ''VARBINARY(MAX)'') FROM ScanIT_tblProjektbilder Where ID='''+ #PicID +''')'
creates this string:
(Select Cast('' AS XML).value('xs:base64Binary(sql:column("ImportPictureData"))', 'VARBINARY(MAX)') FROM ScanIT_tblProjektbilder Where ID='105')
DECLARE #ImageData VARBINARY(max);
select #ImageData = (Select Cast('' AS XML).value('xs:base64Binary(sql:column("ImportPictureData"))', 'VARBINARY(MAX)') FROM ScanIT_tblProjektbilder Where ID='105')
When I assign this string as a hardcopy to the variable #ImageData I do not get any error, if I am going to assign the variable #sqlDynamicString to the variable #ImageData like
select #ImageData = #sqlDynamicString
I get an
error 257: Implicit conversion from datatype 'VARCHAR' to 'VARBINARY(MAX)' is not allowed. Use CONVERT-Function
what is going wrong here??
Even using convert iso cast I get the same error.
Thanks
Execute the code in #sqlDynamicString,store the result in a temp table and then assign to your varbinary variable.
create table #temp
(
imageData varbinary(max)
)
insert into #temp
exec #sqlDynamicString
select #ImageData=(select imageData from #temp)

SQL Query to update a colums from a table base on a datetime field

I have 2 table called tblSetting and tblPaquets.
I need to update 3 fields of tblPaquets from tblSetting base on a where clause that use a datetime field of tblPaquest and tblSetting.
The sql below is to represent what I am trying to do and I know it make no sense right now.
My Goal is to have One query to achieve this goal.
I need to extract the data from tblSettings like this
SELECT TOP(1) [SupplierID],[MillID],[GradeFamilyID] FROM [tblSettings]
WHERE [DateHeure] <= [tblPaquets].[DateHeure]
ORDER BY [DateHeure] DESC
And Update tblPaquets with this data
UPDATE [tblPaquets]
SET( [SupplierID] = PREVIOUS_SELECT.[SupplierID]
[MillID] = PREVIOUS_SELECT.[MillID]
[GradeFamilly] = PREVIOUS_SELECT.[GradeFamilyID] )
Here the table design
CREATE TABLE [tblSettings](
[ID] [int] NOT NULL,
[SupplierID] [int] NOT NULL,
[MillID] [int] NOT NULL,
[GradeID] [int] NOT NULL,
[TypeID] [int] NOT NULL,
[GradeFamilyID] [int] NOT NULL,
[DateHeure] [datetime] NOT NULL,
[PeakWetEnable] [tinyint] NULL)
CREATE TABLE [tblPaquets](
[ID] [int] IDENTITY(1,1) NOT NULL,
[PaquetID] [int] NOT NULL,
[DateHeure] [datetime] NULL,
[BarreCode] [int] NULL,
[Grade] [tinyint] NULL,
[SupplierID] [int] NULL,
[MillID] [int] NULL,
[AutologSort] [tinyint] NULL,
[GradeFamilly] [int] NULL)
You can do this using CROSS APPLY:
UPDATE p
SET SupplierID = s.SupplierID,
MillID = s.MillID
GradeFamilly = s.GradeFamilyID
FROM tblPaquets p CROSS APPLY
(SELECT TOP (1) s.*
FROM tblSettings s
WHERE s.DateHeure <= p.DateHeure
ORDER BY p.DateHeure DESC
) s;
Notes:
There are no parentheses before SET.
I don't recommend using [ and ] to escape identifiers, unless they need to be escaped.
I presume the query on tblSettings should have an ORDER BY to get the most recent rows.

How to call procedure for each row?

I have a Microsoft SQL Server R2 2008. And i see it first time in my life.
I have sql procedure:
DECLARE #RC int
DECLARE #Id uniqueidentifier
DECLARE #Segment_ID uniqueidentifier
DECLARE #SDate datetime
DECLARE #EDate datetime
DECLARE #withBig bit
DECLARE #withKm bit
DECLARE #withGeo bit
DECLARE #withDescr bit
-- TODO: задайте здесь значения параметров.
EXECUTE #RC = [Request_BusStation]
#Id
,#Segment_ID
,#SDate
,#EDate
,#withBig
,#withKm
,#withGeo
,#withDescr
GO
How i understand its just calling of procedure not thetself. But procedure too bit to copy it here.
AND have a table:
CREATE TABLE [BusStation](
[Id] [uniqueidentifier] NOT NULL,
[Segment_ID] [uniqueidentifier] NOT NULL,
[Dist] [decimal](18, 4) NOT NULL,
[Kod_Spr012] [smallint] NOT NULL,
[Square] [decimal](18, 6) NULL,
[OperationStartDate] [date] NULL,
[BallanceCost] [decimal](18, 6) NULL,
[DepreciatedCost] [decimal](18, 6) NULL,
[ChargesNorm] [decimal](18, 6) NULL,
[DocumentName] [varchar](100) NULL,
[DocumentNum] [varchar](100) NULL,
[DocumentDate] [date] NULL,
[Authority] [varchar](100) NULL,
[Kod_Spr091] [smallint] NOT NULL,
[HasWaysideStop] [bit] NOT NULL,
[HasLanding] [bit] NOT NULL,
[HasSpeedTransitArea] [bit] NOT NULL,
[LenSpeedTransitArea] [decimal](18, 6) NULL,
[YearBuilt] [smallint] NULL,
[YearMajorOverhaul] [smallint] NULL,
[Kod_Spr019] [smallint] NOT NULL,
[TechCond] [varbinary](max) NULL,
[LandCont] [varbinary](max) NULL,
[LandContDate] [date] NULL,
[LandContStartDate] [date] NULL,
[LandContEndDate] [date] NULL,
[Kod_Spr120] [smallint] NULL,
[E_Date_Begin] [datetime] NOT NULL,
[E_Date_End] [datetime] NULL,
[E_Date_Stop] [datetime] NULL,
Now i want to call this procedure for each row of table.
Its possible?
Yes, you can use a cursor that selects all the rows in the table and iteratively calls the stored procedure.
I would suggest that you may have a design issue before going down that route though. If the stored procedure needs to be called for every row in the table, you may be able to write a stored procedure that simply does what your current sp does to all the rows instead of a single row operation.
You have not provided what the sp is doing so I can only speculate here.
As mentioned in my comment, the only way I would know how to do that is using a CURSOR. Here is some sample code (untested of course):
DECLARE #ID INT
DECLARE #Segment_ID uniqueidentifier
DECLARE #getAccountID CURSOR
SET #BusStationCursor = CURSOR FOR
SELECT Id, Segment_ID --(etc: all the fields you need)
FROM BusStation
OPEN #BusStationCursor
FETCH NEXT FROM #BusStationCursor INTO #ID, #Segment_ID
WHILE ##FETCH_STATUS = 0
BEGIN
--CALL YOUR SP HERE
PRINT #ID
PRINT #Segment_ID
FETCH NEXT FROM #BusStationCursor INTO #ID, #Segment_ID
END
CLOSE #BusStationCursor
DEALLOCATE #BusStationCursor
This should help as well:
http://msdn.microsoft.com/en-us/library/ms180169.aspx
Good luck.

SQL query that can display data with a null ID and with not null id on the same Datatable?

Hello I have a question here...
I'll show you my tables first...
[Vendedores](
[IdVendedor] [int] IDENTITY(1,1) NOT NULL,
[IdGrupo] [int] NULL,
[IdInfoContacto] [int] NULL,
[ApellidoPaterno] [varchar](30) NULL,
[ApellidoMaterno] [varchar](30) NULL,
[Nombre] [varchar](35) NULL,
[Estado] [varchar](10) NULL,
CONSTRAINT [PK_Vendedores] PRIMARY KEY CLUSTERED
[Clientes](
[IdCliente] [int] IDENTITY(1,1) NOT NULL,
[IdGrupo] [int] NULL,
[IdVendedor] [int] NULL,
[IdDireccion] [int] NULL,
[IdInfoContacto] [int] NULL,
[FechaAlta] [date] NULL,
[ApellidoPaterno] [varchar](30) NULL,
[ApellidoMaterno] [varchar](30) NULL,
[Nombre] [varchar](40) NULL,
[Empresa] [text] NULL,
[Estado] [varchar](20) NULL,
[Estatus] [varchar](20) NULL,
CONSTRAINT [PK_Clientes] PRIMARY KEY CLUSTERED
[dbo].[Mensajes](
[IdMensaje] [int] IDENTITY(1,1) NOT NULL,
[IdCliente] [int] NULL,
[IdVendedor] [int] NULL,
[CorreoRemitente] [varchar](100) NULL,
[CorreoCliente] [varchar](100) NULL,
[CorreosAdicionales] [varchar](max) NULL,
[Tema] [varchar](100) NULL,
[Mensaje] [varchar](max) NULL,
[Fecha] [date] NULL,
[Hora] [time](5) NULL,
CONSTRAINT [PK_Mensajes] PRIMARY KEY CLUSTERED
[Archivos](
[IdArchivo] [int] IDENTITY(1,1) NOT NULL,
[IdMensaje] [int] NULL,
[Nombre] [varchar](max) NULL,
[Ubicacion] [varchar](50) NULL,
CONSTRAINT [PK_Archivos] PRIMARY KEY CLUSTERED
There are 2 ways to send messages in the system I'm developing...:
the first one is, you select a client, and when the message is sent, the client's ID (IdCliente) is taken from Clientes Table and inserted in a new row in Mensajes table.
that way, when you want to check all of the sent messages, you can clearly see to which client was sent.
the second one would be a free one, you send to whoever you want, you don't have to select a client. Therefore, when you register the new message, the IdCliente column would be null.
Some notes out of the way now: Vendedor is the seller or user who sent the message, Archivos means files, and in case you want to attach files, for each one of them, a new row in Archivos would be inserted and each with the same IdMensaje.
FOR THE moment, I have a query that allows me to see all my messages (with clients), and to also show how many files were attached to that message. HERE IT IS:
SELECT (Clientes.ApellidoPaterno + ' ' + Clientes.ApellidoMaterno + ' ' + Clientes.Nombre) AS Cliente, Mensajes.* FROM (SELECT Mensajes.IdMensaje, Mensajes.IdCliente, Mensajes.IdVendedor, Mensajes.CorreoRemitente, Mensajes.CorreoCliente, Mensajes.CorreosAdicionales, Mensajes.Tema, Mensajes.Mensaje, Mensajes.Fecha, Mensajes.Hora, COUNT(Archivos.IdArchivo) AS Archivos FROM Mensajes LEFT OUTER JOIN Archivos ON Mensajes.IdMensaje = Archivos.IdMensaje GROUP BY Mensajes.IdMensaje, Mensajes.IdCliente, Mensajes.IdVendedor, Mensajes.CorreoRemitente, Mensajes.CorreoCliente, Mensajes.CorreosAdicionales, Mensajes.Tema, Mensajes.Mensaje, Mensajes.Fecha, Mensajes.Hora) AS Mensajes JOIN Clientes ON Clientes.IdCliente = Mensajes.IdCliente ORDER BY Mensajes.Fecha DESC, Mensajes.Hora DESC
"(Clientes.ApellidoPaterno + ' ' + Clientes.ApellidoMaterno + ' ' + Clientes.Nombre) AS Cliente" Displays the full name of the client
however, now I want to have a query in which displays the same information as above... plus the following...
Messages with IdCliente = null
if IdCliente = null then the Cliente Column that I mentioned above would be "" (blank space)
If I need to be more specific, please let me know in what part must I give more information.
I hope you guys can help me
Thanks in advance
Firstly, change your JOIN to a LEFT JOIN:
LEFT JOIN Clientes ON Clientes.IdCliente = Mensajes.IdCliente
This will allow Messages with no associated IdCliente to remain. To get the desired blank space, use COALESCE:
COALESCE(Clientes.ApellidoPaterno + ' ' + Clientes.ApellidoMaterno + ' ' + Clientes.Nombre, '') AS Cliente