I have a table that holds form details, the form num(identity column) and the 5 columns for the Questions Score.
My insert proc for the form is very basic:
ALTER PROC [dbo].[Insert_New_Form]
#questionOne int, #questionTwo int, #questionThree int,
#questionFour int, #questionFive Int as
begin
Insert into Questionire_Form values (
#questionOne, #questionTwo, #questionThree,
#questionFour, #questionFive)
end
and I hold an int call answer that it's value changes between radio button selection (scoring).
My question is, how do I write a procedure to insert all of the answers in one row, meaning at each click on "next" button the score for the specific answer will be inserted to the row at the specific column.
and how do I wirte the update procedure should I use chack again button to go through the form?
I am using MS SQL 2012
I hope the following code will help you
CREATE PROCEDURE add_Score
#userID INT
#questionNumber INT,
#score INT
AS
DECLARE #ColumnaName VARCHAR(100)
DECLARE #sql VARCHAR(1000)
SET #ColumnName =
( CASE #questionNumber
WHEN 1 THEN 'ColumnOne'
WHEN 2 THEN 'ColumnTwo'
WHEN 3 THEN 'ColumnThree'
WHEN 4 THEN 'ColumnFour'
END )
IF EXISTS(SELECT * FROM Questionire_Form WHERE UserID = #userID) THEN
BEGIN
SET #sql = 'UPDATE Questionire_Form SET ' + #ColumnName + ' = ' + #score + ' WHERE UserID = ' + #userID
END
ELSE
BEGIN
SET #sql = 'INSERT INTO Questionire_Form (UserID, ' + #ColumnName + ') VALUES(' + #userID + ', ' + #score + ')'
END
EXEC(#sql)
Related
I was looking how I can parameterize table names and so I found dynamic sql queries. I finally got the proc saved, but when I execute it errors out with "Conversion failed when converting the varchar value ' AND ID =' to data type int." I have no idea what is going wrong when I try to execute this stored proc. I feel like it must be a typo but I cannot tell. The stored pro.
EDITED to incorporate the suggestion below. Still no luck unless I am doing this wrong.
-- =======================================================
-- Create Stored Procedure Template for Azure SQL Database
-- =======================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author, , Name>
-- Create Date: <Create Date, , >
-- Description: <Description, , >
-- =============================================
ALTER PROCEDURE [dbo].[sp_GetFormFieldCDC]
(
#formfieldId INT,
#C___operation INT,
#C___start_lsn binary(10),
#tablename NVarchar(255)
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
DECLARE #ActualTableName AS NVarchar(255)
SELECT #ActualTableName = QUOTENAME( TABLE_NAME )
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #tablename
DECLARE #sql AS NVARCHAR(MAX)
SELECT #sql = 'SELECT * FROM ' + #ActualTableName + ' WHERE __$start_lsn =' + CONVERT(NVARCHAR(255),#C___start_lsn) + ' AND __$operation =' + #C___operation + ' AND ID =' + #formfieldId + ';'
-- Insert statements for procedure here
EXEC sp_executesql #SQL, N' #formfieldId INT,
#C___operation INT,
#C___start_lsn binary(10),
#tablename NVarchar(255)', #formfieldId ,
#C___operation,
#C___start_lsn,
#tablename
END
GO
You should pass the parameters all the way through to sp_executesql. Do not inject them, unless they are object names, in which case you need QUOTENAME.
You can also use OBJECT_ID to check for table existence, and throw an exception if there is no such object.
CREATE OR ALTER PROCEDURE [dbo].[GetFormFieldCDC]
(
#formfieldId INT,
#C___operation INT,
#C___start_lsn binary(10),
#schemaname sysname,
#tablename sysname
)
AS
SET NOCOUNT ON;
IF (OBJECT_ID(QUOTENAME(#schemaname) + '.' + QUOTENAME(#tablename)) IS NULL)
THROW 50000, 'Table not found', 0;
DECLARE #sql AS NVARCHAR(MAX) = '
SELECT *
FROM ' + QUOTENAME(#schemaname) + '.' + QUOTENAME(#tablename) + '
WHERE __$start_lsn = #C___start_lsn
AND __$operation = #C___operation
AND ID = #formfieldId;
';
EXEC sp_executesql #SQL,
N' #formfieldId INT,
#C___operation INT,
#C___start_lsn binary(10)',
#formfieldId = #formfieldId,
#C___operation = #C___operation,
#C___start_lsn = #C___start_lsn;
GO
I want to be able to merge duplicate records in 1 table, and update all child entities whose FK was the originalRecordId to the destinyRecordId. This could be done manually, but it would be a daunting task as the parent table could have 40+ relationships, and this has to be done in multiple parent tables. I am using EF 6 with code first.
I have been able to get all navigation properties using the following (credit goes to #zev-spits in this question):
public List<PropertyInfo> GetNavigationProperties(T entity)
{
var t = entity.GetType();
var elementType = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet<T>().EntitySet.ElementType;
return elementType.NavigationProperties.Select(np => entityType.GetProperty(np.Name)).ToList();
}
I have no idea where to go from here.
Is there a way to programmatically do this task? I would like to pass in a originalRecord and a destinyRecord, obtain all related entities of the originalRecord and update the FK with the destinyRecordId.
I finally took #mjwillis suggestion and resolved this directly in SQL Server with the following:
DECLARE #sql nvarchar (255);
DECLARE #refTableName varchar(255) = 'Opportunities'
DECLARE #refColName varchar(255) = 'Id'
DECLARE #refValue uniqueidentifier = '2a8a0f61-fe5c-4dd7-8e6d-00c8340333c4'
Deleted User Key
DECLARE #refNewValue uniqueidentifier = '99999999-9999-9999-9999-999999999999'
DECLARE RelatedTableCursor CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT
result.TableName,
result.ColumnName
FROM
(
SELECT
OBJECT_NAME(f.parent_object_id) AS TableName,
COL_NAME(fc.parent_object_id,fc.parent_column_id) AS ColumnName,
SCHEMA_NAME(o.SCHEMA_ID) ReferenceSchemaName,
OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
COL_NAME(fc.referenced_object_id,fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id
INNER JOIN sys.objects AS o ON o.OBJECT_ID = fc.referenced_object_id
) result
WHERE
ReferenceTableName = #refTableName AND ReferenceColumnName = #refColName
OPEN RelatedTableCursor
WHILE 1 = 1
BEGIN
DECLARE #tableName varchar(255)
DECLARE #columnName varchar(255)
FETCH NEXT FROM RelatedTableCursor into #tableName, #columnName
IF ##fetch_status <> 0
BEGIN
BREAK
END
DECLARE #sql nvarchar (255);
SET #sql =
N'UPDATE [' + #tableName + '] ' +
'SET ' +
' [' + #columnName + '] = ''' + CONVERT(NVARCHAR(255), #refNewValue) + ''' ' +
'WHERE [' + #columnName + '] = ''' + CONVERT(NVARCHAR(255), #refValue) + ''' ';
-- Prevent some error (Duplicate record) that occurs when replace data in mapping table.
BEGIN TRY
-- exec sp_executesql #sql;
select #sql
END TRY
BEGIN CATCH
END CATCH
END
CLOSE RelatedTableCursor
DEALLOCATE RelatedTableCursor
SET #sql = 'DELETE FROM [' + #refTableName + '] WHERE ' + #refColName + ' = ''' + CONVERT(NVARCHAR(255), #refValue) + '''';
EXEC sp_executesql #sql;
Using the below stored procedure I am able to select a variable section of a table, given the Row index of each record. I tried to create another stored procedure similar to the MulTselect, only this time the table value parameter will have another column for the new value for a MulTUpdate stored procedure.
[RowIndex] int, [NewVal] [varchar] (4000) NOT NULL
the question is, given the record - Rowindex and "NewValue", is it possible to do an UPDATE on multiple records like in select procedure below?
--sproc signature
CREATE Proc [dbo].[MulTSELECTViaRowIndexSpTVP]
#SelectedTableName varchar (50),
#SelectedAction varchar(10),
#TestMulTSELECTViaRowIndexTVPar dbo.TestMulTSELECTViaRowIndexTVType READONLY
SET #CmdStr = 'SELECT * FROM ' + #SelectedTableName + '
WHERE RowIndex in (SELECT RowIndex from #TestMulTSELECTViaRowIndexTVPar);'
EXEC sp_executesql #CmdStr,N' #TestMulTSELECTViaRowIndexTVPar dbo.TestMulTSELECTViaRowIndexTVType READONLY',
#TestMulTSELECTViaRowIndexTVPar= #TestMulTSELECTViaRowIndexTVPar
AS I was looking through my old stored procedures i found one that stared me thinking in the right way, so this is what i got to compile, not yet tested.
Declare #TotalRec int = (Select COUNT(RowIndex) from #TestMulTiActMulTColIndexTVPar);
Declare #Iter int =0, #Count int =0;
While #Iter < #TotalRec
Begin
Declare #curRowIndex int=
(
select RowIndex from
(select row_number() over (order by RowIndex) as RowN,
* from #TestMulTiActMulTColIndexTVPar) T where T.RowN =(#Iter+1)
);
Declare #CurVal varchar(4000) = (Select [StrVal] from #TestMulTiActMulTColIndexTVPar WHERE RowIndex=#curRowIndex);
SET #CmdStr = 'UPDATE ' + #SelectedSDTOName + ' SET ' + #SelectedColName + ' = ' + QUOTENAME(#CurVal, '''') + ' WHERE RowIndex = ' + CAST(#curRowIndex as nvarchar);
EXEC sp_executesql #CmdStr,N' #TestMulTiActMulTColIndexTVPar dbo.TestMulTiActMulTColIndexTVType READONLY',
#TestMulTiActMulTColIndexTVPar= #TestMulTiActMulTColIndexTVPar;
Set #Iter = #Iter + 1;
End
SELECT 'EffRows' = #Iter;
this is the best i could compose with my skills,
as it iterates it's executing each update command(within the while loop) separately as opposed to the select procedure
SELECT * FROM ' + #SelectedTableName + '
WHERE RowIndex in (SELECT RowIndex from #TestMulTSELECTViaRowIndexTVPar);'
so i don't know if it will best perform as i coded here...
any comment will be very welcome.
and thanks for your time.
I want to PassColumn name as a paremeter in My SP
And if my tat column exists in first table (Batch_Master), want to fatch value from that column,
And if that column exists in my second table (GTIN_Master), want to fetch value from tat table column,
Each table have columns like..
Batch_Master (Batch_M_id, GTIN(primary key),....etc
GTIN_Master (GTIN (foreign key),..etc)
I have Batch_M_id, and column name as a parameter..
Note: column Name having random datatype, some time int or some time datetime etc
I Try followin SP
CREATE PROCEDURE dbo.StoredProcedure2
#columnName varchar(50),
#batchmId int
AS
if exists(select * from sys.columns
where Name = N'columnName' and Object_ID = Object_ID(NBatch_Master'))
begin
select #columnName from Batch_Master
end
else
begin
select #columnName
from GTIN_Master inner join Batch_Master
on GTIN_Master.GTIN = Batch_Master.GTIN
where Batch_M_id =#batchmId
end
RETURN
What you need when you do not know exactly the query structure you are going to execute, then you have to create a dynamic query, which is actually a form of templating queries.
CREATE PROCEDURE dbo.StoredProcedure2
#columnName varchar(50),
#batchmId int
AS
DECLARE #SQL1 AS VARCHAR(MAX)
DECLARE #SQL2 AS VARCHAR(MAX)
SET #SQL1 = 'select ' + #columnName + ' from Batch_Master'
SET #SQL1 = 'select ' + #columnName + '
from GTIN_Master inner join Batch_Master
on GTIN_Master.GTIN = Batch_Master.GTIN
where Batch_M_id =' + CONVERT(VARCHAR,#batchmId)
IF EXISTS(SELECT * FROM sys.columns WHERE Name = #columnName and Object_ID = Object_ID(N'Batch_Master'))
BEGIN
EXEC (#SQL1)
END
ELSE
BEGIN
EXEC (#SQL2)
END
The above will do what you want but is prone to errors. For instance what if the column passed in the parameter does not exist in the tables used in the second query? You should probably need to check for existence in the second case too.
DECLARE #SQL VARCHAR(MAX)
SET #SQL = 'select ' + #columnName + ' from Batch_Master'
EXECUTE(#SQL)
This SQL:
set nocount on
go
create table One (id int, name varchar(25))
go
create table Two (id int, value varchar(25))
go
insert into One values (1, 'Table One')
insert into Two values (1, 'Table Two')
go
create procedure sp_test_colname
#colname sysname
as
declare #sql nvarchar(2048)
if exists (select 1 from sys.columns where name = #colname and object_id = object_id(N'One'))
set #sql = 'select [' + #colname + '] from [One]'
else
if exists (select 1 from sys.columns where name = #colname and object_id = object_id(N'Two'))
set #sql = 'select [' + #colname + '] from [Two]'
if #sql <> ''
exec sp_executesql #sql
go
exec sp_test_colname 'name'
exec sp_test_colname 'value'
exec sp_test_colname 'somethingelse'
go
drop procedure sp_test_colname
drop table One, Two
Returns the following:
name
-------------------------
Table One
value
-------------------------
Table Two
I am working on a project and I got stuck with a query in which I want to get the specific column name of a table whose value is "no."
I have a table with name subscription and it has four fields; id(integer), email(varchar), sms(varchar), phone(varchar) and my email, sms and phone field have values either 'yes' or 'no'.
Now I want to retrieve the name of only those columns which has a value 'no'.
I want to execute this query in mysql.
I have tried the following query which is returning me the complete row wherever there is even one occurence of 'no':
SELECT * FROM test.subscription WHERE 'no' IN (email,sms,phone);
Like i have these two rows now i want to select the column name where value='no' and id=1
How about something cheap and cheerful using a case statement like:
SELECT ID, 'ColName' = CASE
WHEN email = 'no' THEN 'email'
END,
'ColName2' = CASE
WHEN sms = 'no' THEN 'sms'
END,
'ColName3' = CASE
WHEN phone = 'no' THEN 'phone'
END
FROM subscription
where ID = 2
I cant put this as a comment because of less privileges, but if you are looking to search a value which is held by a table (could be any column) - you might check this SO post
Using the code from the same post -
DECLARE #Results TABLE(ColumnName nvarchar(370), ColumnValue nvarchar(3630))
DECLARE #SearchStr nvarchar(100)
DECLARE #TableName nvarchar(256), #ColumnName nvarchar(128), #SearchStr2 nvarchar(110)
SET #TableName = 'no'
SET #SearchStr2 = QUOTENAME('%' + 'no' + '%','''')
SET #ColumnName = ''
SET #TableName = '[test].[dbo].[subscription]'
WHILE (#TableName IS NOT NULL) AND (#ColumnName IS NOT NULL)
BEGIN
SET #ColumnName =
(
SELECT MIN(QUOTENAME(COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(#TableName, 2)
AND TABLE_NAME = PARSENAME(#TableName, 1)
AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
AND QUOTENAME(COLUMN_NAME) > #ColumnName
)
IF #ColumnName IS NOT NULL
BEGIN
INSERT INTO #Results
EXEC
(
'SELECT ''' + #TableName + '.' + #ColumnName + ''', LEFT(' + #ColumnName + ', 3630)
FROM ' + #TableName + ' (NOLOCK) ' +
' WHERE ' + #ColumnName + ' LIKE ' + #SearchStr2
)
END
END
SELECT ColumnName, ColumnValue FROM #Results
If i got the Question right, i think the following Query might work
SELECT *
FROM test.subscription
WHERE 1=1
and
(email = 'no'
or
email = 'no'
or
sms = 'no'
)
and id=(your values)