If parameter is null, pull results from table - sql

This might be a stupid question, but I haven't found a way to word this to get an answer that suits what I'm trying to accomplish. I might just be having a stupid moment.
I have an input variable for a sproc; that input variable may be passed in as null.
If the value is null, I would like insert into a temp table a list of values from another table. Otherwise, I'd just like to insert into the temple table the value of the parameter.
What I'm trying to do is something like this
INSERT INTO #tempTable
SELECT (CASE WHEN #myVariable IS NULL
THEN (SELECT [myVariable] FROM myTable)
ELSE #myVariable END)
This won't work because that select statement pulls back a large number of results (and it's malformed), but that's the general idea. I basically want to have an optional parameter where the user can specify a specific ID, or get back ALL the IDs.
Does anyone have any suggestions on the best way to go about this?
Thank you!

I think this UNION will do
INSERT INTO #tempTable
SELECT #myVariable WHERE #myVariable IS NOT NULL
UNION
SELECT [myVariable] FROM myTable WHERE #myVariable IS NULL
Of course if it doesn't need to be one query - you can use simple IF logic
IF #myVariable IS NULL
INSERT INTO #tempTable
SELECT [myVariable] FROM myTable
ELSE
INSERT INTO #tempTable
SELECT #myVariable

Would something like this work for you?
SELECT DISTINCT ISNULL(#myVariable, myVariableColumn)
FROM myTable

I suggest this query:
INSERT INTO #tempTable
SELECT CASE WHEN #myVariable IS NULL Then [myVariable] else #myVariable end FROM myTable

Related

Using Common Table Expression and IF EXISTS

I am running a query similar to
DECLARE #VARIABLE NVARCHAR(50) = 'VALUE';
WITH MYCTE_TABLE (Column1,Column2)
AS
SELECT
(ColumnA, Column B
FROM
SomeTable
WHERE
ColumnA = SomeValue)
IF EXISTS(SELECT ColumnZ FROM AnotherTable WHERE Columnz = SomeNumbers)
BEGIN
SELECT * FROM MYCTE_TABLE
END
ELSE
BEGIN
MYSUBQUERY2
END
...
However, I keep getting the following error:
Incorrect syntax near the keyword 'IF'.
Each subquery works well when run independently. It seems the use of a common table expression before the IF EXISTS is causing the issue.
Any help please?
I really doubt, that this is the best approach... You tried to clean and shorten this for brevitiy (thumbs up for this!), but the given information is - maybe - not enough.
You cannot use a CTE in different queries. A CTE is fully inlined as part of the query...
But you could write your values into a table variable like here:
DECLARE #tbl TABLE(Column1 INT, Column2 VARCHAR(100)); --Choose appropriate types
INSERT INTO #tbl
SELECT ColumnA, ColumnB FROM SomeTable WHERE ColumnA=SomeValue;
This table variable can be used in later queries (but in the same job!) like any other table:
SELECT *
FROM SomeTable AS st
INNER JOIN #tbl AS tbl ON ...
... or similiar usages...
Another approach might be this
SELECT Column1,Column2 INTO #SomeTempTable FROM SomeWhere
This will write the result of the SELECT into a temp table (which is session wide).
I'm quite sure, that there might be a better (set-based) approach... Are the two sub-queries identical in their result set's structure? If so, you might use UNION ALL and place your "IF EXISTS" as a WHERE-clause to each sub query.
IF is control flow. WITH is within a query. You can do:
IF EXISTS (SELECT ColumnZ FROM AnotherTable WHERE Columnz=SomeNumbers)
BEGIN
WITH MYCTE_TABLE (Column1,Column2)AS
SELECT (ColumnA, Column B FROM SomeTable WHERE ColumnA=SomeValue)
MYSUBQUERY1
END;
ELSE
BEGIN
WITH MYCTE_TABLE (Column1,Column2)AS
SELECT (ColumnA, Column B FROM SomeTable WHERE ColumnA=SomeValue)
MYSUBQUERY2
END;
Or you could use a temporary table or table variable to store the values.

Error converting varchar to bigint

I got the error where my data type is varchar, then I want to insert value/input in textboxt = 'smh85670s'.
It appear to be error. As far as I know varchar can accept characters and numbers, but why does it keep throwing this error?
If I insert value '123456' the table can accept that value.
Please guide me. What data type should I use?
Assuming that you are using Stored procedures (which have an insert query) or directly firing an insert query into DB, you must be sending all data as parameters like say #param1, #param2,...
Your insert query will be like
INSERT INTO Sometable ( Amount, textbox,... )
SELECT #param1, #param2 ,...
Just add a cast in this query to make it work
INSERT INTO Sometable ( Amount, textbox,... )
SELECT #param1, CAST(#param2 as varchar),...

Using a string of quoted values in a variable for a SQL WHERE CLAUSE

The answer escapes me...maybe because it is not possible...
Example that works...
SELECT * FROM TABLEA WHERE FIELD1 IN ('aaa','bbb','ccc')
Example that does not work...
Attempt to leverage variable so that I can define the values once in a string of statements
DECLARE #ListValues VARCHAR(50)
SET #ListValues = '''aaa'',''bbb'',''ccc'''
SELECT * FROM TABLEA WHERE FIELD1 IN (#ListValues)
This is is obviously only a small part of the equation and for other reasons...
I cannot leverage a table for the values and change this to a true sub-query
The closest question I could find was this one... but does not cover my requirements obviously...
Storing single quotes in varchar variable SQL Server 2008
Thanks in advance.
You can do this using dynamic SQL:
DECLARE #ListValues VARCHAR(MAX)
,#SQL VARCHAR(MAX)
SELECT #ListValues = '''aaa'',''bbb'',''ccc'''
,#SQL = 'SELECT * FROM TABLEA WHERE FIELD1 IN ('+#ListValues+')'
EXEC (#SQL)
It doesn't work because the IN operator expects a list of items - here strings.
What you're supplying with your #ListValues variable however is a single string - not a list of strings.
What you could do is use a table variable and store your values in it:
DECLARE #ListOfValues TABLE (ItemName VARCHAR(50))
INSERT INTO #ListOfValues(ItemName)
VALUES('aaa'), ('bbb'), ('ccc')
SELECT *
FROM TABLEA
WHERE FIELD1 IN (SELECT ItemName FROM #ListOfValues)
Build your whole SQL query dynamically (say it's stored in a string variable #sql),
and then execute it with EXEC (#sql). Better yet, use the sp_executesql SP
because this approach is more secure (less prone to SQL injection) than EXEC.
See: sp_executesql
The IN operator in SQLServer expect a list of values, your variable is a single string, the query parsed will be different
SELECT * FROM TABLEA WHERE FIELD1 IN ('aaa','bbb','ccc')
SELECT * FROM TABLEA WHERE FIELD1 IN ("'aaa','bbb','ccc'")
Attention: the double quotes are there only for readability, to get the string with single quote in it.
if you know a programming language the first one is like searching in an array, the second is a string.
To store a list in your variable it need to a table
DECLARE #varTable TABLE (field1 varchar())
So that you can use it in your IN
SELECT * FROM TABLEA WHERE FIELD1 IN (SELECT field1 FROM #varTable)
To add values to the table variable use an INSERT statament like usual for tables.

Referring to column values directly without using variables in T-SQL

Is there a way in T-SQL (SQL Server 2005) to assign a whole record to a record variable and then refer to the particular values using column names?
I mean, instead of:
select #var1 = col1,
#var2 = col2
from mytable
where ID = 1;
and referring to them as #var1 and #var2, something like
#record =
select col1, col2
from mytable
where ID = 1;
and referring to them like #record.col1 and #record.col2 .
I am beginner in t-sql, so hopefully the question is not too trivial.
You can create a table variable and select the whole resultset into it:
DECLARE #tt TABLE (col1 INT, col2 INT)
INSERT
INTO #tt
SELECT col1, col2
FROM mytable
WHERE id = 1
, but you cannot access its data except than in the SELECT query as well.
With pure TSQL (that it without custom datatypes) the thing you ask is impossible.
sounds like you are a programmer ... look at linq maybe as it does what you want.
You can use a temporary table and SELECT...INTO to avoid specifying the column names at the beginning :
SELECT Field1, Field2
INTO #TempTable
FROM MyTable
WHERE MyTable.MyID = 1
but of course you'll still need the FROM #TempTable part when referring to the column names.
SELECT Field1, Field2
FROM #TempTable
and of course to remember to drop the table at the end :
DROP #TempTable
The app code is where you'd normally refer to a single row at a time as a variable.
You could use XML, but you'd have to play with this...
DECLARE #MyRecord xml
DECLARE #Mytable TABLE (col1 int NOT NULL, col2 varchar(30) NOT NULL)
INSERT #Mytable (col1, col2) VALUES (1, 'bob')
select #MyRecord =
(SELECT *
from #Mytable
where col1 = 1
FOR XML AUTO)
SELECT #myRecord.value('./#col', 'int') --also #myRecord.value('#col', 'int')
--gives error
Msg 2390, Level 16, State 1, Line 12
XQuery [value()]: Top-level attribute nodes are not supported
Buried in the Transact SQL documentation I came across this restriction on variables:
Variables can be used only in expressions, not in place of object names or keywords.
Since you'd need to use an object name to qualify a column I don't believe that this is allowed.

How do I return a new IDENTITY column value from an SQLServer SELECT statement?

I'm inserting into an SQLServer table with an autoincrementing key field. (I believe this is called an IDENTITY column in SQLServer.)
In Oracle, I can use the RETURNING keyword to give my INSERT statement a results set like a SELECT query that will return the generated value:
INSERT INTO table
(foreign_key1, value)
VALUES
(9, 'text')
RETURNING key_field INTO :var;
How do I accomplish this in SQLServer?
Bonus: Okay, nice answers so far, but how do I put it into a single statement, if possible? :)
In general, it can't be done in a single statement.
But the SELECT SCOPE_IDENTITY() can (and should) be placed directly after the INSERT statement, so it's all done in the same database call.
Example:
mydb.ExecuteSql("INSERT INTO table(foreign_key1, value) VALUES(9, 'text'); SELECT SCOPE_IDENTITY();");
You can use OUTPUT, but it has some limitations you should be aware of:
http://msdn.microsoft.com/en-us/library/ms177564.aspx
SELECT SCOPE_IDENTITY()
Edit: Having a play...
If only the OUTPUT clause supported local variables.
Anyway, to get a range of IDs rather than a singleton
DECLARE #Mytable TABLE (keycol int IDENTITY (1, 1), valuecol varchar(50))
INSERT #Mytable (valuecol)
OUTPUT Inserted.keycol
SELECT 'harry'
UNION ALL
SELECT 'dick'
UNION ALL
SELECT 'tom'
Edit 2: In one call. I've never had occasion to use this construct.
DECLARE #Mytable TABLE (keycol int IDENTITY (1, 1), valuecol varchar(50))
INSERT #Mytable (valuecol)
OUTPUT Inserted.keycol
VALUES('foobar')
In addition to ##IDENTITY, you should also look into SCOPE_IDENTITY() and IDENT_CURRENT(). You most likely want SCOPE_IDENTITY(). ##IDENTITY has a problem in that it might return an identity value created in a trigger on the actual table that you're trying to track.
Also, these are single-value functions. I don't know how the Oracle RETURNING keyword works.
SCOPE_IDENTITY
It depends on your calling context.
If you're calling this from client code, you can use OUTPUT and then read the value returned.
DECLARE #t TABLE (ColID int IDENTITY, ColStr varchar(20))
INSERT INTO #t (ColStr)
OUTPUT Inserted.ColID
VALUES ('Hello World')
Result:
ColID
-----------
1
If you're wrapping this in a stored procedure, using OUTPUT is more work. There, you'll want to use SCOPE_IDENTITY(), but you can't do it in a single statement. Sure, you can put multiple statements on a single line with a ';' separator, but that's not a single statement.
DECLARE #idValue int
DECLARE #t TABLE (ColID int IDENTITY, ColStr varchar(20))
INSERT INTO #t (ColStr) VALUES ('Hello World')
SELECT #idValue = SCOPE_IDENTITY()
Result: #idValue variable contains identity value. Use an OUTPUT parameter to return the value.
You can use OUTPUT INTO, which has the additional benefits of being able to capture multiple identities inserted.
INSERT INTO table(foreign_key1, value)VALUES(9, 'text');SELECT ##IDENTITY;