First the solution is working perfect, and after as per our Project Manager requirement I have added two column in table. After that one insert,update store procedure is not working it show "Invalid column name" (it mention newly inserted two column name). I think some details is stored in temporary but I don't know how to find and solve it.
I tried something like this:
Removed all constrain and tried to run the store procedure, but no use
Just removed the newly added two column, it is working perfect.
Tried to add the column through an Alter query
My stored procedure is
ALTER PROCEDURE [Page].[SP_INSERT_EXPERIENCEDETAILS]
(#EXPERIENCEDETAILS [PAGE].[EXPERIENCEDETAILS] READONLY)
AS --drop PROCEDURE [Page].[SP_INSERT_EXPERIENCEDETAILS]
BEGIN
DECLARE #TEMPTABLE AS TABLE
(
ID INT,
[ACTION] VARCHAR(50)
)
MERGE INTO [PAGE].[EXPERIENCEDETAILS] AS TARGET
USING (SELECT
ID, Description, ISCurrent, COMPANYID,
Designationid, locationid, FROMDAY, FromMonth, FromYear,
TODAY, TOMONTH, Toyear
FROM
#EXPERIENCEDETAILS) AS SOURCE ON TARGET.ID = SOURCE.ID
WHEN MATCHED THEN
UPDATE
SET TARGET.[DESCRIPTION] = SOURCE.[DESCRIPTION],
TARGET.ISCURRENT = SOURCE.ISCURRENT,
TARGET.COMPANYID = SOURCE.COMPANYID,
TARGET.DESIGNATIONID = SOURCE.DESIGNATIONID,
TARGET.LOCATIONID = SOURCE.LOCATIONID,
TARGET.FROMDAY = SOURCE.FROMDAY,
TARGET.FROMMONTH = SOURCE.FROMMONTH,
TARGET.FROMYEAR = SOURCE.FROMYEAR,
TARGET.TODAY = SOURCE.TODAY,
TARGET.TOMONTH = SOURCE.TOMONTH,
TARGET.TOYEAR = SOURCE.TOYEAR
WHEN NOT MATCHED THEN
INSERT
VALUES (SOURCE.MEMBERID, SOURCE.PAGEID, SOURCE.COMPANYID,
SOURCE.DESIGNATIONID, SOURCE.LOCATIONID,
SOURCE.FROMDAY, SOURCE.FROMMONTH, SOURCE.FROMYEAR,
SOURCE.TODAY, SOURCE.TOMONTH, SOURCE.TOYEAR,
SOURCE.[DESCRIPTION], SOURCE.[ISCURRENT],
SOURCE.ENTRYDATE)
OUTPUT INSERTED.ID, $ACTION INTO #TEMPTABLE;
SELECT ID FROM #TEMPTABLE
END
Error shown in the following lines
TARGET.FROMDAY= SOURCE.FROMDAY
TARGET.TODAY=SOURCE.TODAY
SOURCE.FROMDAY
SOURCE.TODAY
You should also add those columns in table type [PAGE].[EXPERIENCEDETAILS] that used in your SP as TVP type.
Related
I have a stored procedure and am using a Merge Statement to Insert and Update. This aspect is working as I require.
However, the output when inserting the record is always 1 and I cannot see why? I would be grateful if someone could review this procedure and let me know what I could be doing wrong,.
CREATE PROCEDURE [dbo].[FileAdd]
#FileId int,
#FileData varbinary(max),
#ContentType Varchar(100),
#OperatorId int
AS
BEGIN
--In Memory Table to
DECLARE #MergeOutput TABLE
(
Id INT
);
--Merge needs a table to Merge with so using a CTE
WITH CTE AS (
SELECT #FileId as FileId)
--Merge
MERGE INTO [dbo].[Files] as T
USING CTE AS S
ON T.FileId = S.FileId
WHEN NOT MATCHED THEN
INSERT (
FileData,
ContentType,
OperatorIdCreated,
OperatorIdUpdated
)
VALUES(
#FileData,
#ContentType,
#OperatorId,
#OperatorId
)
WHEN MATCHED THEN
UPDATE SET
FileData = #FileData,
ContentType= #ContentType,
OperatorIdUpdated = #OperatorId,
Updated = GetDate()
OUTPUT
INSERTED.FileId
INTO #MergeOutput;
SELECT * FROM #MergeOutput;
END
GO
The reason you are getting 1 is because that is what is being UPDATED or INSERTED. When it's the UPDATED value, then it is the value are passing into #FileID.
With the OUTPUT clause:
INSERTED Is a column prefix that specifies the value added by the
insert or update operation.
Thus, what ever value is UPDATED (which is #FileID) or INSERTED (which will be whatever your FileID table logic is) this will be returned in your code. If you are always getting 1, then you must me always updating the column for FileID = 1.
Changing your bottom to inserted.* would show you this, as it would OUTPUT the updated row.
Check the demo here.
I have one table and I am willing to fill two columns with values generated using other column value using function.
NOTE: I am working with a .mdf file in Visual Studio and not SQL Server.
Like if EmployeeName is 'XYZ' then Password will be 'XYZ#123' and mailid will be 'XYZ#gmail.com'
Here is the procedure
CREATE FUNCTION [dbo].[fnTempSetAllEmployeeMailIdAndEmployeePassword]()
RETURNS #OutputTable TABLE
(
EmployeeName NVARCHAR(250),
TempEmployeeMailId NVARCHAR(250),
TempEmployeePassword NVARCHAR(250)
)
AS
BEGIN
DECLARE #Initialiser INT = 1, #NumberOfRowsInTable INT, #TempEmployeeId INT, #TempEmployeeName NVARCHAR(250);
SELECT #NumberOfRowsInTable = COUNT(*)
FROM tbEmployee;
WHILE(#Initialiser <= #NumberOfRowsInTable)
BEGIN
SELECT
#TempEmployeeName = [EmployeeName],
#TempEmployeeId = [EmployeeId]
FROM
(SELECT
ROW_NUMBER() OVER(ORDER BY [EmployeeId] ASC) AS ROwNumber,
[EmployeeId], [EmployeeName]
FROM
tbEmployee) AS TempTable
WHERE
RowNumber = #Initialiser;
UPDATE tbEmployee
SET [EmployeeMailId] = LOWER(#TempEmployeeName) + '#gmail.com',
[EmployeePassword] = LOWER(#TempEmployeeName) + '#123'
WHERE [EmployeeId] = #TempEmployeeId;
SET #Initialiser = #Initialiser + 1;
END
INSERT #OutputTable
SELECT [EmployeeName], [EmployeeMailId], [EmployeePassword]
FROM tbEmployee;
RETURN
END
The problem is the above statements works when I execute in new query file.
But when I put in function and try to update it. I will not save and says something went wrong when executing.
But saves when I comment the UPDATE command.
Is it problem with Update being in while loop?
There are a couple of things going on here.
Firstly, the reason that it doesn't work in a function is because in SQL Server functions cannot change anything in the database. You are attempting to change the data in the table and that isn't allowed. It would be allowed in a stored procedure.
Secondly, it looks like a pretty inefficient way of doing the update. For each iteration of the loop this code:
grabs all the employees, sorts them
takes a single row and updates it
inserts that row into a table variable to later output
As a starting point, try just updating every single row in the table in one go:
CREATE PROCEDURE dbo.TempSetAllEmployeeMailIdAndEmployeePassword AS
BEGIN
UPDATE tbEmployee
SET [EmployeeMailId] = LOWER(#TempEmployeeName) + '#gmail.com',
[EmployeePassword] = LOWER(#TempEmployeeName) + '#123';
SELECT EmployeeName, EmployeeMailID, EmployeePassword
FROM tblEmployee;
END
If it turns out that you have problems because there are too many rows that you're trying to update at once, then maybe you could look at batching, but that's probably a separate topic.
How to get the value after updating the table using triggers in sql
Having a scenario like this:
CREATE TABLE #tmp (id INT, txt VARCHAR(10))
INSERT INTO #tmp ( id, txt )
VALUES ( 1, 'abc')
You can return the values using OUTPUT (https://msdn.microsoft.com/en-us/library/ms177564.aspx) during an UPDATE like this:
UPDATE #tmp SET
txt = 'xyz'
OUTPUT INSERTED.id, INSERTED.txt
You can return any column from your table - INSERTED will contain new data while DELETED will contain previous data.
In the Update SQL it self you can use OUTPUT.
In the triggers on MS SQL servers there are to temp tabels called INSERED and DELETED see her for more info: https://msdn.microsoft.com/en-us/library/ms191300.aspx
Hope it helps.
When I execute a Procedure I would like to UPDATE table1 and SET the new values for the CODE, NUMBER, and ADDRESS columns only if the same CODE and DeptID do not exist. If I change the CODE to an existing name in table1 it is OK as long as the DeptID is different.
Example:
Say I want to change Beta to Delta. That is fine because they have different DeptIDs. So I want to UPDATE everything, aka the third row in my example would now have the values (1, Delta, 'whateverNUMBER', 'whateverADDRESS')
But if I wanted to take that same third row Beta and change the CODE to Alpha I don't want to allow that and I don't want to SET the NUMBER or ADDRESS either because there is already a row with CODE Alpha and DeptID 1.
How would I be able to accomplish this?
Here is one of my attempts which does not work:
UPDATE dbo.table1
SET
CODE = #CODE
,NUMBER = #NUMBER
,ADDRESS = #ADDRESS
WHERE ID = #ID
AND NOT EXISTS
(
SELECT NAME FROM dbo.table1
WHERE NAME = #NAME
AND ID = #ID
)
This should work if you have the commas in the right place for syntax and specify the old code:
UPDATE dbo.table1
SET CODE = #CODE,
NUMBER = #NUMBER,
ADDRESS = #ADDRESS
WHERE ID = #ID AND
CODE = #OLDCODE AND
NOT EXISTS (SELECT 1
FROM dbo.table1
WHERE NAME = #NAME AND ID = #ID
);
The easiest would be to add a unique constraint for columns DeptId and Code.
This will prevent any duplicate insert as well as an update to already existing values.
The constraint will even prevent any changes performed directly against the table and not just within your update statement.
I'm not sure if this is something I should do in T-SQL or not, and I'm pretty sure using the word 'iterate' was wrong in this context, since you should never iterate anything in sql. It should be a set based operation, correct? Anyway, here's the scenario:
I have a stored proc that returns many uniqueidentifiers (single column results). These ids are the primary keys of records in a another table. I need to set a flag on all the corresponding records in that table.
How do I do this without the use of cursors? Should be an easy one for you sql gurus!
This may not be the most efficient, but I would create a temp table to hold the results of the stored proc and then use that in a join against the target table. For example:
CREATE TABLE #t (uniqueid int)
INSERT INTO #t EXEC p_YourStoredProc
UPDATE TargetTable
SET a.FlagColumn = 1
FROM TargetTable a JOIN #t b
ON a.uniqueid = b.uniqueid
DROP TABLE #t
You could also change your stored proc to a user-defined function that returns a table with your uniqueidentifiers. You can joing directly to the UDF and treat it like a table which avoids having to create the extra temp table explicitly. Also, you can pass parameters into the function as you're calling it, making this a very flexible solution.
CREATE FUNCTION dbo.udfGetUniqueIDs
()
RETURNS TABLE
AS
RETURN
(
SELECT uniqueid FROM dbo.SomeWhere
)
GO
UPDATE dbo.TargetTable
SET a.FlagColumn = 1
FROM dbo.TargetTable a INNER JOIN dbo.udfGetUniqueIDs() b
ON a.uniqueid = b.uniqueid
Edit:
This will work on SQL Server 2000 and up...
Insert the results of the stored proc into a temporary table and join this to the table you want to update:
INSERT INTO #WorkTable
EXEC usp_WorkResults
UPDATE DataTable
SET Flag = Whatever
FROM DataTable
INNER JOIN #WorkTable
ON DataTable.Ket = #WorkTable.Key
If you upgrade to SQL 2008 then you can pass table parameters I believe. Otherwise, you're stuck with a global temporary table or creating a permanent table that includes a column for some sort of process ID to identify which call to the stored procedure is relevant.
How much room do you have in changing the stored procedure that generates the IDs? You could add code in there to handle it or have a parameter that lets you optionally flag the rows when it is called.
Use temporary tables or a table variable (you are using SS2005).
Although, that's not nest-able - if a stored proc uses that method then you can't dumpt that output into a temp table.
An ugly solution would be to have your procedure return the "next" id each time it is called by using the other table (or some flag on the existing table) to filter out the rows that it has already returned
You can use a temp table or table variable with an additional column:
DECLARE #MyTable TABLE (
Column1 uniqueidentifer,
...,
Checked bit
)
INSERT INTO #MyTable
SELECT [...], 0 FROM MyTable WHERE [...]
DECLARE #Continue bit
SET #Continue = 1
WHILE (#Continue)
BEGIN
SELECT #var1 = Column1,
#var2 = Column2,
...
FROM #MyTable
WHERE Checked = 1
IF #var1 IS NULL
SET #Continue = 0
ELSE
BEGIN
...
UPDATE #MyTable SET Checked = 1 WHERE Column1 = #var1
END
END
Edit: Actually, in your situation a join will be better; the code above is a cursorless iteration, which is overkill for your situation.