Update Query to match string to column Name - sql

I have the following UI on my program
Then I have a table with the following columns
What I want to do is to write a query that looks at the "Item" string on my combo box and then updates the above column, in this case Handbooks, of the table above where the Generalist name matches the column. The record should be updated every time, in other words, I want to replace the information every time.
I have no idea where to begin on this. This the query I used to create the table I want to update.
SELECT repName.Rep_Name, repName.Handbooks, repName.Leaves
FROM repName INNER JOIN
Positions ON repName.Job_Code = Positions.Job_Code
ORDER BY repName.Rep_Name
In case this helps somewhat

My first guess is, as I put on the comment above, that your design is not well.
Nonetheless if in your scenario you still need to do what you are asking, then you could use dynamic sql:
DECLARE #sqlCommand varchar(1000)
DECLARE #column varchar(50)
SET #column = 'foo'
SET #value = 'bar'
SET #sqlCommand = 'UPDATE TABLE SET ' + #column + ' = ' + #value
EXEC (#sqlCommand)
You could pass the value with parameters or whatever approach is better to your case.

Related

Reference a column value from a temporary table

In a stored procedure I get a record from a table and insert it into a temporary table #temp.
Then in this stored procedure I would like to set a value in a column of the #temp table as follows:
declare #VarName varchar(max)
set #VarName = 'Value is ' + #temp.colname
There is an error on the last line. Of course I can get the value of #temp.varname into another variable, before setting #VarName. But I would like to know if it is possible to do it inline, without another variable name.
I think this is what you mean, but it's pretty brittle in that it assumes you will only ever have one row in #temp.
DECLARE #VarName varchar(max) = (SELECT 'Value is ' + colname FROM #temp);
Example db<>fiddle

Generating filed name with concat

My table has column names m1,m2,m3...,m12.
I'm using iterator to select them and insert them one by one in another table.
In this iterator I'm trying to generate filed names with:
'['+concat('m',cast(#P_MONTH as nvarchar))+']'
where #P_MONTH is incrementing in each loop.
so for #P_MONTH = 1 this suppose to give [m1] which works fine.
But when I run query I get:
Conversion failed when converting the nvarchar value '[m1]' to data
type int.
And if I put simply [m1] in that select it works ok.
How to concat filed name so it can be actually interpreted as filed name from certain table?
EDIT
Here is full query:
DECLARE #SQLString nvarchar(500),
#P_YEAR int,
#P_MONTH int = 1
set #P_YEAR = 2018
WHILE #P_MONTH < 13
BEGIN
SET #SQLString =
'INSERT INTO [dbo].[MASTER_TABLE]
(sector,serial,
date, number, source)'+
'SELECT ' + '[SECTOR],[DEPARTMENT]' +
QUOTENAME(cast(CONVERT(datetime,CONVERT(VARCHAR(4),#P_YEAR)+RIGHT('0'+CONVERT(VARCHAR(2),#P_MONTH),2)+'01',5) as nvarchar))+
QUOTENAME ('M',cast(#P_MONTH as nvarchar)) +
'EMPLOYED' +
'FROM [dbo].[STATS]'+
'where YEAR= #P_YEAR'
EXECUTE sp_executesql #SQLString
SET #P_MONTH = #P_MONTH + 1
END
It's still not working. It executes successfully but it does nothing.
Good day,
Let's create a simple table for the sake of the explanation
DROP TABLE IF EXISTS T
GO
CREATE TABLE T(a1 INT)
GO
INSERT T(a1) VALUES (1),(2)
GO
SELECT a1 FROM T
GO
When we are using a query like bellow, the server parse the text as a value and not as a column name
DECLARE #String NVARCHAR(10)
SELECT #String = '1'
--
SELECT '['+concat('a',cast(#String as nvarchar))+']'
FROM T
GO
This mean that the result will be 2 rows with no name for the column and the value will be "[a1]"
Moreover, the above query uses the brackets as part of the string.
One simple solution is to use the function QUOTENAME in order to add brackets around a name.
Another issue in this approach is the optional risk of SQL Injection. QUOTENAME might not be perfect solution but can help in this as well.
If we need to use entities name dynamically like in this case the column name then for most cases using dynamic query is the best solution. This mean to use the Stored Procedure sp_executesql as bellow
DECLARE #String INT
SELECT #String = 1
DECLARE #SQLString nvarchar(500);
SET #SQLString =
'SELECT ' + QUOTENAME(concat('a',cast(#String as nvarchar))) + ' FROM T'
EXECUTE sp_executesql #SQLString
GO

Passing Multiple Values to Variable in Linked Server Connection String

I have the following query, which pulls data from an Oracle DB into SQL Server 2005:
SELECT *
FROM (
SELECT *
FROM OPENQUERY(LINKEDSERVERNAME, 'SELECT FOO, BAR, FROM TABLE
WHERE ID IN(' + #IDs + '
')) AS TMP
WHERE SOME_ID IN
(SELECT DISTINCT ID
FROM LOCALTABLE);
The runtime, however, is very long, as the query from the linked server results in a large number of rows. I am only interested in a small number of these rows, however the criteria limiting my query are held in the destination database.
Via another post on SO, I see I could potentially use a variable in dynamic sql that looks like:
DECLARE #IDs AS NVARCHAR(100);
SET #IDs = (SELECT ID FROM LOCALTABLE)
DECLARE #sql AS NVARCHAR(3000);
SET #sql = 'SELECT * FROM OPENQUERY(LINKEDSERVERNAME, ''SELECT FOO, BAR, FROM TABLE
WHERE ID IN(' + #IDs + '))'
EXEC sp_executesql #sql
However, I obviously cannot assign more than one value to the variable, and so the result set only contains results for the final ID placed in #IDs.
What is the best strategy for accomplishing this task for all distinct IDs in the local table?
Anup Shah has already pointed out what is wrong in his comment. Your SELECT assignment will only ever put one value into your variable. You need a way to convert your table results to a CSV style for the IN statement. Pinal Dave has a good post which shows a well known technique for doing this with XML PATH.
http://blog.sqlauthority.com/2009/11/25/sql-server-comma-separated-values-csv-from-table-column/
Worth noting that SELECT #var = #var + var FROM table IS NOT a valid way of doing this, although it may appear to work in some cases.
James

t-sql string & table column manipulation

DETAILS table has following columns
Title First Second Third Fourth Fifth
------------------------------------------
A null null null null null
input variable
--------------
#columns = 'Title, Third, Fourth'
I want to generate ouput as
#allcolumns = 'Title, Third, Fourth, First, Second, Fifth'
Variable #allcolumns will contain all columns from DETAILS table but with #columns first and then the remaining columns
So for instance if
#columns = 'Title, Fourth,Fifth'
then output will be
#allcolumns = 'Title, Fourth, Fifth, First, Second, Third'
Thanks
This should work:
DECLARE #columns VARCHAR(max);
DECLARE #allcolumns VARCHAR(max);
SET #columns = 'Title,Fourth,Fifth';
SET #allcolumns = #columns;
SELECT #allcolumns = #allcolumns + ',' + column_name FROM
INFORMATION_SCHEMA.columns WHERE
table_name = 'DETAILS' AND
CHARINDEX(column_name, #columns) = 0;
SELECT #allcolumns;
GO
An additional thought: if you want to create a SELECT statement to select the columns in the order generated by the above code, you could do this:
DECLARE #sql VARCHAR(max);
SET #sql = 'SELECT ' + #allcolumns + ' FROM DETAILS';
EXEC(#sql);
...although I can't see why you would want to do that.
There are many ways to do this. Being your question is rather general, I would suggest looking at the following link and using your INFORMATION_SCHEMA views if using SQL Server.
http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/
First and most importantly, why not simply return columns First through Fifth and let the calling code determine which columns to use? The SQL language in general was not designed for dynamic column determination and generation. It presumes that the calling code handles the determination of the columns that should be returned. Further, calling code should never depend on the column order in a query and therefore the order of the columns in the output should make no difference. Given that, you should do this type of manipulation in a middle-tier component or reporting tool.
Second, while it is possible to solve this type of problem in T-SQL, it should not be done. T-SQL is awful for string manipulation.
Lastly, if this is the type of query you need to build to get the proper information from your database schema, you might need to re-evaluate your database schema. When you start running into more and more complicated queries in order to retrieve the information you want, it is indicative of a schema that is out of touch with the business needs.

Help with TSQL - a way to get the value in the Nth column of a row?

I hope to find a way to get the value in the Nth column of a dataset.
Thus, for N = 6 I want
SELECT (Column6Value) from MyTable where MyTable.RowID = 14
Is there a way to do this in TSQL as implemented in SQL Server 2005? Thanks.
You should be able to join with the system catalog (Information_Schema.Columns) to get the column number.
This works:
create table test (a int, b int, c int)
insert test values(1,2,3)
declare #column_number int
set #column_number = 2
declare #query varchar(8000)
select #query = COLUMN_NAME from information_Schema.Columns
where TABLE_NAME = 'test' and ORDINAL_POSITION = #column_number
set #query = 'select ' + #query + ' from test'
exec(#query)
But why you would ever do something like this is beyond me, what problem are you trying to solve?
Not sure if you're at liberty to redesign the table, but if the ordinal position of the column is significant, your data is not normalized and you're going to have to jump through lots of hoops for many common tasks.
Instead of having table MyTable with Column1... ColumnN you'd have a child table of those values you formerly stored in Column1...ColumnN each in their own row.
For those times when you really need those values in a single row, you could then do a PIVOT: Link
Edit: My suggestion is somewhat moot. Ash clarified that it's "de-normalization by design, it's a pivot model where each row can contain one of any four data types." Yeah, that kind of design can be cumbersome when you normalize it.
If you know the range of n you could use a case statement
Select Case when #n = 1 then Column1Value when #n = 2 then Column2Value end
from MyTable
As far as I know there is no dynamic way to replace a column (or table) in a select statement without resorting to dynamic sql (in which chase you should probably refactor anyways)
Implementation of #Mike Sharek's answer.
Declare #columnName varchar(255),
#tablename varchar(255), #columnNumber int, #SQL nvarchar(4000)
Set #tablename = 'MyTable'
Set #columnNumber = 6
Select #columnName = Column_Name from Information_SChema.columns
where Ordinal_position = #columnNumber and Table_Name = #tablename
Set #SQL = 'select ' + #columnName + ' from ' + #tableName + ' where RowID=14'
Exec sp_Executesql #SQL
I agree with Sambo - why are you trying to do this? If you are calling the code from C# or VB, its much easier to grab the 6th column from a resultset.