SQL Server Dynamic SQL Query - sql

I have a text file with about 400,000 records which have to be read, processed and inserted into a table. I'm using a stored procedure to do the same. The records are pipe separated as shown below
a | b | c .... 180 columns (1st record)
d | e | f .... 180 columns (2nd record)
.
.
.
x | y | z .....180 columns (4,00,00th record)
In the stored procedure, one insert statement was being fired for each record. I created a dynamic SQL query that would club 1,000 records in one insert but noticed that the execution time did not decrease. In fact, the SQL dynamic query created for a single record (includes isnull and cast functions for each column) takes more time than than the time taken to insert a single record into the table.
Is there a way I reduce the time taken to perform the task at hand?
EDIT
The dynamic SQL query looks something like this (just a tiny snapshot)
CAST(GETDATE() AS VARCHAR(20)) + ''',' +
CAST(#N_ER AS VARCHAR(20)) + ',' +
CAST(#N_INSDE AS VARCHAR(20)) + ',' +
CAST(#N_CODE AS VARCHAR(20)) + ',' +
CAST(#NJOB_NUMBER AS VARCHAR(30)) + ',' +
CAST(#NNUMBER AS VARCHAR(30)) + ',''' +
ISNULL(DESTINATION,'') + ''',''' +
ISNULL(#VPE_ID,'') + ''',''' +
ISNULL(dbo.fn_NEW_CARD(#VAN),'') +
Or is there a way to improve the concatenation using some other set of functions maybe?

Instead of using EXEC to run your Dynamic SQL - have you tried ExecuteSQL (with parameters) The advantage is that SQL can cache the query plan - which is a fairly significant saving on 400K inserts.
To be honest - SSIS is by far the best way to do it - Right click on the DB, select Tasks and Import Data then follow the wizard - you can even save the created package for later use in a Job.

Related

How to create a script to create a table

I am using SQL Server Management Studio 2017. I'm having a table in my local machine. Let's say its name is Email. Inside the Email table, there is a column name Language and its value can be 'en' or 'zh'. Beside this Language column, there are some more columns.
Now my colleague also has the same table but different machine and he only has the rows where Language is en. He doesn't have the rows where Language is zh yet.
How can I use this software to generate a SQL script to insert data to his table but with rows only where Language = 'zh' so that both table will be the same.
To be more clear , I need to send him the INSERT script with also contains the values of the data, so that he can use to INSERT to his database in his local machine.
Or is it any way else?
Is this what you want?
insert into colleague.dbo.email ( . . . )
select . . .
from my.dbo.email
where language = 'zh';
There are a couple of ways - the first is quick and requires no code, but you need to manually get rid of the rows you don't want yourself, the other is more flexible but you have to code it. There are also third party tools you can get to do this for you.
If you just want to do this once, you can do the following (this is from a different version of SSMS, but it should be similar)
right click on the database, select tasks, select generate scripts. Then pick the table you want, go next, then in the advanced settings find the "types of data to script" and change it to data. This should generate a script to load all the data from your table - you would need to edit it to just load the rows you want.
Another option is to write a script that basically makes the data you want yourself. You would need set it up to start with, and adjust it if you ever change the table format, but you can edit the selection script so that it only gets the data you want. I'm sure you could write a script that would create this automatically for you, but I've never needed one, so I haven't thought about it.
Something like this one
With baseRows as
(
--This bit gets the data you want
Select E.*
, ROW_NUMBER() over(ORDER BY ID) as RowNo
From dbo.Email E
Where E.Language = 'zh' -- whatever selection you need here
)
, selectRows as
(
--This bit creates the data select statments to set the data to import
Select
case when BR.RowNo = 1 then '' else 'Union All ' end
+ 'Select '
+ convert(varchar(10), BR.userID) + ' as userID, ' -- required integer example
+ case when BR.backupID is null then 'NULL' else CONVERT(varchar(10), BR.backupID) end + ' as backupID, ' -- nullable integer example
+ '''' + BR.Name + ''' as name, ' -- required nvarchar example
+ case when BR.groupname IS null then 'NULL' else '''' + BR.groupname + '''' end + ' as groupname, ' --nullable varchar example
+ CONVERT(varchar(2), BR.isActive) + ' as isActive, ' --bit example
as SQL
from baseRows BR
)
Select
--This creates the insert command row (top row) of the final query
'Insert into Email (
userID
, backupID
, name
, groupName
, IsActive
)' as SQL
UNION ALL
Select SQL from baseRows --and adds the data to the following rows
If you run this script, the output would be the script you are looking for to load the data into another machine.
RightClick on Database name(table in which Database)--->Tasks--->Generate Scripts--->Next--->select specific database objects--->select Table--->Save to file = ADVANCED--->click on Advanced--->types of data to script = "Data Only"--->Give the path(where to store theinsert commands)

SQL Update a column in a table using Trigger to a Function

I am trying to auto generate a document reference number when a new document is added to an sql table - the reference number is a concatonation of some of the other fields in that table.
Looking online i can see one method is to use the dbid function to generate a uid and then create a function to concatonate and then a trigger on the table on insert to populate the column, but ive spent numerous hours and i cant get it to work.
The table has the following columns:-
Table:- dbo.codeallocations21322
Columns :-
Dbid
Projectcode
Type
Discipline]
Hdlreference
So the hdlreference column would be populated with :-
[projectcode]-[type]-[discipline]-[bdid]
With the [bdid] set to 6 characters'.
Eg 21322-rfq-mech-000001
Any help would be much appreciated / advise a better way ?
Many thanks in advance.
You can use a computed column
alter table codeallocations21322
add hdlreference
as ( projectcode + '-' + type + '-' + discipline + '-' + dbid);
Many thanks John - altered slightly to convert the Int dbID to a varchar and works great :-
alter table CodeAllocations21322
add hdlreference2
as (ProjectCode + '-' + Type + '-' + Discipline + '-' + right('00000' + Cast (dbID AS varchar(5)), 5));
Thanks again, look forward to talking to you in the future.

Execute table valued function from row values

Given a table as below where fn contains the name of an existing table valued functions and param contains the param to be passed to the function
fn | param
----------------
'fn_one' | 1001
'fn_two' | 1001
'fn_one' | 1002
'fn_two' | 1002
Is there a way to get a resulting table like this by using set-based operations?
The resulting table would contain 0-* lines for each line from the first table.
param | resultval
---------------------------
1001 | 'fn_one_result_a'
1001 | 'fn_one_result_b'
1001 | 'fn_two_result_one'
1002 | 'fn_two_result_one'
I thought I could do something like (pseudo)
select t1.param, t2.resultval
from table1 t1
cross join exec sp_executesql('select * from '+t1.fn+'('+t1.param+')') t2
but that gives a syntax error at exec sp_executesql.
Currently we're using cursors to loop through the first table and insert into a second table with exec sp_executesql. While this does the job correctly, it is also the heaviest part of a frequently used stored procedure and I'm trying to optimize it. Changes to the data model would probably imply changes to most of the core of the application and that would cost more then just throwing hardware at sql server.
I believe that this should do what you need, using dynamic SQL to generate a single statement that can give you your results and then using that with EXEC to put them into your table. The FOR XML trick is a common one for concatenating VARCHAR values together from multiple rows. It has to be written with the AS [text()] for it to work.
--=========================================================
-- Set up
--=========================================================
CREATE TABLE dbo.TestTableFunctions (function_name VARCHAR(50) NOT NULL, parameter VARCHAR(20) NOT NULL)
INSERT INTO dbo.TestTableFunctions (function_name, parameter)
VALUES ('fn_one', '1001'), ('fn_two', '1001'), ('fn_one', '1002'), ('fn_two', '1002')
CREATE TABLE dbo.TestTableFunctionsResults (function_name VARCHAR(50) NOT NULL, parameter VARCHAR(20) NOT NULL, result VARCHAR(200) NOT NULL)
GO
CREATE FUNCTION dbo.fn_one
(
#parameter VARCHAR(20)
)
RETURNS TABLE
AS
RETURN
SELECT 'fn_one_' + #parameter AS result
GO
CREATE FUNCTION dbo.fn_two
(
#parameter VARCHAR(20)
)
RETURNS TABLE
AS
RETURN
SELECT 'fn_two_' + #parameter AS result
GO
--=========================================================
-- The important stuff
--=========================================================
DECLARE #sql VARCHAR(MAX)
SELECT #sql =
(
SELECT 'SELECT ''' + T1.function_name + ''', ''' + T1.parameter + ''', F.result FROM ' + T1.function_name + '(' + T1.parameter + ') F UNION ALL ' AS [text()]
FROM
TestTableFunctions T1
FOR XML PATH ('')
)
SELECT #sql = SUBSTRING(#sql, 1, LEN(#sql) - 10)
INSERT INTO dbo.TestTableFunctionsResults
EXEC(#sql)
SELECT * FROM dbo.TestTableFunctionsResults
--=========================================================
-- Clean up
--=========================================================
DROP TABLE dbo.TestTableFunctions
DROP TABLE dbo.TestTableFunctionsResults
DROP FUNCTION dbo.fn_one
DROP FUNCTION dbo.fn_two
GO
The first SELECT statement (ignoring the setup) builds a string which has the syntax to run all of the functions in your table, returning the results all UNIONed together. That makes it possible to run the string with EXEC, which means that you can then INSERT those results into your table.
A couple of quick notes though... First, the functions must all return identical result set structures - the same number of columns with the same data types (technically, they might be able to be different data types if SQL Server can always do implicit conversions on them, but it's really not worth the risk). Second, if someone were able to update your functions table they could use SQL injection to wreak havoc on your system. You'll need that to be tightly controlled and I wouldn't let users just enter in function names, etc.
You cannot access objects by referencing their names in a SQL statement. One method would be to use a case statement:
select t1.*,
(case when fn = 'fn_one' then dbo.fn_one(t1.param)
when fn = 'fn_two' then dbo.fn_two(t1.param)
end) as resultval
from table1 t1 ;
Interestingly, you could encapsulate the case as another function, and then do:
select t1.*, dbo.fn_generic(t1.fn, t1.param) as resultval
from table1 t1 ;
However, in SQL Server, you cannot use dynamic SQL in a user-defined function (defined in T-SQL), so you would still need to use case or similar logic.
Either of these methods is likely to be much faster than a cursor, because they do not require issuing multiple queries.

Comparing values between two rows of data and only showing the columns that are different

In a previous application version we were using a particular field for a primary key, but because the field may represent different identities across various systems we have made it a non significant field(ie not a primary key or part of a composite primary) however since we dont have another system yet users still use that field as a primary method of identification.
The problem is with auditing...previously I used a single table to do all audits for the database dumping the data with a newvalue oldvalue schema using the generic trigger that is floating around. This could still work fine except for one thing. I have moved contactinformation into a separate table that is tied to the new primary key of the original table. So when changes are made the unfamiliar and unused primary key shows in the auditlog instead of the now insignificant foreignSystemID...
I moved to doing a one to one copy method of auditing so that any changes to any table are now written to a mirror image in a different schema. The problem comes down to showing changes to the users. They are used to seeing a report that shows only the changed values for a particular doctor...
My question would be using sql queries and Crystal reports, how could I show only the changed column values between rows in my audit tables. I have looked at the pivot command, but I dont think thats really going to help me. I had also looked at the code within the script that compares the columns and determines if they are different and writes them to the table.
im really spinning in the sand here and this is a critical issue for me to solve. Thanks in advance for ANY help...
we are early enough into production that I could change my changetracking method if need be, but it needs to be soon. thanks
EDIT:
My boss and I have worked on this a bit and this is what we have started with...I would like to get further opinions and options...as well...thanks..
CREATE TABLE #TEMP (
DoctorsID bigint,
TableName varchar(50),
FieldName varchar(50),
CurrentFieldValue varchar(255),
PreviousFieldValue varchar(255),
PreviousValueDate datetime
)
DECLARE #sql varchar(MAX)
SELECT
#sql = COALESCE(#sql,'') +
CAST(
'INSERT INTO #TEMP ' +
'SELECT ' +
'o.DoctorsID, ' +
'''' + TABLE_NAME + ''' ,' +
'''' + COLUMN_NAME + ''',' +
'o.' + COLUMN_NAME + ',' +
'a.' + COLUMN_NAME + ',' +
'a.AuditDate' +
' FROM ' +
'dbo.DoctorLicenses o ' +
'INNER JOIN Audit.DoctorLicenses a ON ' +
'o.DoctorsID = a.DoctorsID ' +
'WHERE ' +
'AuditDate BETWEEN ''10/01/2010'' AND ''10/31/2010'' AND ' +
'o.' + COLUMN_NAME + ' <> a.' + COLUMN_NAME +
';'
AS varchar(MAX))
FROM
INFORMATION_SCHEMA.COLUMNS AS [Fields]
WHERE
TABLE_SCHEMA = 'dbo' AND
TABLE_NAME = 'DoctorLicenses'
PRINT #sql
EXEC(#sql)
SELECT * FROM #TEMP
DROP TABLE #TEMP
It sounds to me like there is a design issue, but I have a hard time envisioning what your design is at the moment. Can you be more specific on what your tables look like at the moment and what data you're trying to generate the report(s) on?
Also, when talking about auditing "the changed values", how do you keep track of what's been changed?

Exclude a column using SELECT * [except columnA] FROM tableA?

We all know that to select all columns from a table, we can use
SELECT * FROM tableA
Is there a way to exclude column(s) from a table without specifying all the columns?
SELECT * [except columnA] FROM tableA
The only way that I know is to manually specify all the columns and exclude the unwanted column. This is really time consuming so I'm looking for ways to save time and effort on this, as well as future maintenance should the table has more/less columns.
You can try it this way:
/* Get the data into a temp table */
SELECT * INTO #TempTable
FROM YourTable
/* Drop the columns that are not needed */
ALTER TABLE #TempTable
DROP COLUMN ColumnToDrop
/* Get results and drop temp table */
SELECT * FROM #TempTable
DROP TABLE #TempTable
No.
Maintenance-light best practice is to specify only the required columns.
At least 2 reasons:
This makes your contract between client and database stable. Same data, every time
Performance, covering indexes
Edit (July 2011):
If you drag from Object Explorer the Columns node for a table, it puts a CSV list of columns in the Query Window for you which achieves one of your goals
If you don't want to write each column name manually you can use Script Table As by right clicking on table or view in SSMS like this:
Then you will get whole select query in New Query Editor Window then remove unwanted column like this:
Done
The automated way to do this in SQL (SQL Server) is:
declare #cols varchar(max), #query varchar(max);
SELECT #cols = STUFF
(
(
SELECT DISTINCT '], [' + name
FROM sys.columns
where object_id = (
select top 1 object_id from sys.objects
where name = 'MyTable'
)
and name not in ('ColumnIDontWant1', 'ColumnIDontWant2')
FOR XML PATH('')
), 1, 2, ''
) + ']';
SELECT #query = 'select ' + #cols + ' from MyTable';
EXEC (#query);
A modern SQL dialect like BigQuery proposes an excellent solution.
SELECT * EXCEPT(ColumnNameX, [ColumnNameY, ...])
FROM TableA
This is a very powerful SQL syntax to avoid a long list of columns that need to be updated all the time due to table column name changes. And this functionality is missing in the current SQL Server implementation, which is a pity. Hopefully, one day, Microsoft Azure will be more data scientist-friendly.
Data scientists like to have a quick option to shorten a query and remove some columns (due to duplication or any other reason).
https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select-modifiers
You could create a view that has the columns you wish to select, then you can just select * from the view...
Yes it's possible (but not recommended).
CREATE TABLE contact (contactid int, name varchar(100), dob datetime)
INSERT INTO contact SELECT 1, 'Joe', '1974-01-01'
DECLARE #columns varchar(8000)
SELECT #columns = ISNULL(#columns + ', ','') + QUOTENAME(column_name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'contact' AND COLUMN_NAME <> 'dob'
ORDER BY ORDINAL_POSITION
EXEC ('SELECT ' + #columns + ' FROM contact')
Explanation of the code:
Declare a variable to store a comma separated list of column names. This defaults to NULL.
Use a system view to determine the names of the columns in our table.
Use SELECT #variable = #variable + ... FROM to concatenate the
column names. This type of SELECT does not not return a result set. This is perhaps undocumented behaviour but works in every version of SQL Server. As an alternative you could use SET #variable = (SELECT ... FOR XML PATH('')) to concatenate strings.
Use the ISNULL function to prepend a comma only if this is not the
first column name.
Use the QUOTENAME function to support spaces and punctuation in column names.
Use the WHERE clause to hide columns we don't want to see.
Use EXEC (#variable), also known as dynamic SQL, to resolve the
column names at runtime. This is needed because we don't know the column names at compile time.
Like the others have said there is no way to do this, but if you're using Sql Server a trick that I use is to change the output to comma separated, then do
select top 1 * from table
and cut the whole list of columns from the output window. Then you can choose which columns you want without having to type them all in.
Basically, you cannot do what you would like - but you can get the right tools to help you out making things a bit easier.
If you look at Red-Gate's SQL Prompt, you can type "SELECT * FROM MyTable", and then move the cursor back after the "*", and hit <TAB> to expand the list of fields, and remove those few fields you don't need.
It's not a perfect solution - but a darn good one! :-) Too bad MS SQL Server Management Studio's Intellisense still isn't intelligent enough to offer this feature.......
Marc
DECLARE #SQL VARCHAR(max), #TableName sysname = 'YourTableName'
SELECT #SQL = COALESCE(#SQL + ', ', '') + Name
FROM sys.columns
WHERE OBJECT_ID = OBJECT_ID(#TableName)
AND name NOT IN ('Not This', 'Or that');
SELECT #SQL = 'SELECT ' + #SQL + ' FROM ' + #TableName
EXEC (#SQL)
UPDATE:
You can also create a stored procedure to take care of this task if you use it more often.
In this example I have used the built in STRING_SPLIT() which is available on SQL Server 2016+,
but if you need there are pleanty of examples of how to create it manually on SO.
CREATE PROCEDURE [usp_select_without]
#schema_name sysname = N'dbo',
#table_name sysname,
#list_of_columns_excluded nvarchar(max),
#separator nchar(1) = N','
AS
BEGIN
DECLARE
#SQL nvarchar(max),
#full_table_name nvarchar(max) = CONCAT(#schema_name, N'.', #table_name);
SELECT #SQL = COALESCE(#SQL + ', ', '') + QUOTENAME([Name])
FROM sys.columns sc
LEFT JOIN STRING_SPLIT(#list_of_columns_excluded, #separator) ss ON sc.[name] = ss.[value]
WHERE sc.OBJECT_ID = OBJECT_ID(#full_table_name, N'u')
AND ss.[value] IS NULL;
SELECT #SQL = N'SELECT ' + #SQL + N' FROM ' + #full_table_name;
EXEC(#SQL)
END
And then just:
EXEC [usp_select_without]
#table_name = N'Test_Table',
#list_of_columns_excluded = N'ID, Date, Name';
no there is no way to do this. maybe you can create custom views if that's feasible in your situation
EDIT May be if your DB supports execution of dynamic sql u could write an SP and pass the columns u don't want to see to it and let it create the query dynamically and return the result to you. I think this is doable in SQL Server atleast
If you are using SQL Server Management Studio then do as follows:
Type in your desired tables name and select it
Press Alt+F1
o/p shows the columns in table.
Select the desired columns
Copy & paste those in your select query
Fire the query.
Enjoy.
If you want to exclude a sensitive case column like the password for example, I do this to hide the value :
SELECT * , "" as password FROM tableName;
The best way to solve this is using view you can create view with required columns and retrieve data form it
example
mysql> SELECT * FROM calls;
+----+------------+---------+
| id | date | user_id |
+----+------------+---------+
| 1 | 2016-06-22 | 1 |
| 2 | 2016-06-22 | NULL |
| 3 | 2016-06-22 | NULL |
| 4 | 2016-06-23 | 2 |
| 5 | 2016-06-23 | 1 |
| 6 | 2016-06-23 | 1 |
| 7 | 2016-06-23 | NULL |
+----+------------+---------+
7 rows in set (0.06 sec)
mysql> CREATE VIEW C_VIEW AS
-> SELECT id,date from calls;
Query OK, 0 rows affected (0.20 sec)
mysql> select * from C_VIEW;
+----+------------+
| id | date |
+----+------------+
| 1 | 2016-06-22 |
| 2 | 2016-06-22 |
| 3 | 2016-06-22 |
| 4 | 2016-06-23 |
| 5 | 2016-06-23 |
| 6 | 2016-06-23 |
| 7 | 2016-06-23 |
+----+------------+
7 rows in set (0.00 sec)
In summary you cannot do it, but I disagree with all of the comment above, there "are" scenarios where you can legitimately use a *
When you create a nested query in order to select a specific range out of a whole list (such as paging) why in the world would want to specify each column on the outer select statement when you have done it in the inner?
In SQL Management Studio you can expand the columns in Object Explorer, then drag the Columns tree item into a query window to get a comma separated list of columns.
If we are talking of Procedures, it works with this trick to generate a new query and EXECUTE IMMEDIATE it:
SELECT LISTAGG((column_name), ', ') WITHIN GROUP (ORDER BY column_id)
INTO var_list_of_columns
FROM ALL_TAB_COLUMNS
WHERE table_name = 'PUT_HERE_YOUR_TABLE'
AND column_name NOT IN ('dont_want_this_column','neither_this_one','etc_column');
Postgres sql has a way of doing it
pls refer:
http://www.postgresonline.com/journal/archives/41-How-to-SELECT-ALL-EXCEPT-some-columns-in-a-table.html
The Information Schema Hack Way
SELECT 'SELECT ' || array_to_string(ARRAY(SELECT 'o' || '.' || c.column_name
FROM information_schema.columns As c
WHERE table_name = 'officepark'
AND c.column_name NOT IN('officeparkid', 'contractor')
), ',') || ' FROM officepark As o' As sqlstmt
The above for my particular example table - generates an sql statement that looks like this
SELECT o.officepark,o.owner,o.squarefootage
FROM officepark As o
Is there a way to exclude column(s) from a table without specifying
all the columns?
Using declarative SQL in the usual way, no.
I think your proposed syntax is worthy and good. In fact, the relational database language 'Tutorial D' has a very similar syntax where the keywords ALL BUT are followed by a set of attributes (columns).
However, SQL's SELECT * already gets a lot a flak (#Guffa's answer here is a typical objection), so I don't think SELECT ALL BUT will get into the SQL Standard anytime soon.
I think the best 'work around' is to create a VIEW with only the columns you desire then SELECT * FROM ThatView.
I do not know of any database that supports this (SQL Server, MySQL, Oracle, PostgreSQL). It is definitely not part of the SQL standards so I think you have to specify only the columns you want.
You could of course build your SQL statement dynamically and have the server execute it. But this opens up the possibility for SQL injection..
Right click table in Object Explorer, Select top 1000 rows
It'll list all columns and not *. Then remove the unwanted column(s). Should be much faster than typing it yourself.
Then when you feel this is a bit too much work, get Red Gate's SQL Prompt, and type ssf from tbl, go to the * and click tab again.
I know this is a little old, but I had just run into the same issue and was looking for an answer. Then I had a senior developer show me a very simple trick.
If you are using the management studio query editor, expand the database, then expand the table that you are selecting from so that you can see the columns folder.
In your select statement, just highlight the referenced columns folder above and drag and drop it into the query window. It will paste all of the columns of the table, then just simply remove the identity column from the list of columns...
A colleage advised a good alternative:
Do SELECT INTO in your preceding query (where you generate or get the
data from) into a table (which you will delete when done). This will
create the structure for you.
Do a script as CREATE to new query
window.
Remove the unwanted columns. Format the remaining columns
into a 1 liner and paste as your column list.
Delete the table you
created.
Done...
This helped us a lot.
Actually snowflake just released exclude so now you'd just:
SELECT * EXCLUDE [columnA,columnB,...] FROM tableA
Well, it is a common best practice to specify which columns you want, instead of just specifying *. So you should just state which fields you want your select to return.
That what I use often for this case:
declare #colnames varchar(max)=''
select #colnames=#colnames+','+name from syscolumns where object_id(tablename)=id and name not in (column3,column4)
SET #colnames=RIGHT(#colnames,LEN(#colnames)-1)
#colnames looks like column1,column2,column5
I did it like this and it works just fine (version 5.5.41):
# prepare column list using info from a table of choice
SET #dyn_colums = (SELECT REPLACE(
GROUP_CONCAT(`COLUMN_NAME`), ',column_name_to_remove','')
FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE
`TABLE_SCHEMA`='database_name' AND `TABLE_NAME`='table_name');
# set sql command using prepared columns
SET #sql = CONCAT("SELECT ", #dyn_colums, " FROM table_name");
# prepare and execute
PREPARE statement FROM #sql;
EXECUTE statement;
Sometimes the same program must handle different database stuctures. So I could not use a column list in the program to avoid errors in select statements.
* gives me all the optional fields. I check if the fields exist in the data table before use. This is my reason for using * in select.
This is how I handle excluded fields:
Dim da As New SqlDataAdapter("select * from table", cn)
da.FillSchema(dt, SchemaType.Source)
Dim fieldlist As String = ""
For Each DC As DataColumn In DT.Columns
If DC.ColumnName.ToLower <> excludefield Then
fieldlist = fieldlist & DC.Columnname & ","
End If
Next
In Hive Sql you can do this:
set hive.support.quoted.identifiers=none;
select
`(unwanted_col1|unwanted_col2|unwanted_col3)?+.+`
from database.table
this gives you the rest cols
The proposed answer (stored procedure) from BartoszX didn't work for me when using a view instead of a real table.
Credit for the idea and the code below (except for my fix) belongs to BartoszX.
In order that this works for tables as well as for views, use the following code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[select_without]
#schema_name sysname = N'dbo',
#table_name sysname,
#list_of_columns_excluded nvarchar(max),
#separator nchar(1) = N','
AS
BEGIN
DECLARE
#SQL nvarchar(max),
#full_table_name nvarchar(max) = CONCAT(#schema_name, N'.', #table_name);
SELECT #SQL = COALESCE(#SQL + ', ', '') + QUOTENAME([Name])
FROM sys.columns sc
LEFT JOIN STRING_SPLIT(#list_of_columns_excluded, #separator) ss ON sc.[name] = ss.[value]
WHERE sc.OBJECT_ID = OBJECT_ID(#full_table_name)
AND ss.[value] IS NULL;
SELECT #SQL = N'SELECT ' + #SQL + N' FROM ' + #full_table_name;
EXEC(#SQL)
END
GO