I have 4-5 tables in one database (not SQL Server).
In my UI, users can enter some SQL conditions together with column names in a textbox. I need to verify if the SQL is correct and if these columns exist, and show any errors accordingly. I am using C# for server side.
I have a SQL Server database where our UI stores all the UI related information.
One approach is to create all these tables (just the table structure) in my SQL Server as well and then query a simple select on each table and show the errors or success message(s) accordingly.
So basically I would have the where clause as below or more conditions:
where a = b and c in(1,2)
As mentioned above I would execute the above where clause against each table I created in SQL Server which would return error if column does not exist.
Is there a better way to approach this? I was thinking in case there is some other way to work without creating so many tables on my SQL Server.
I don't want to hard code these as the structure might change in near future. So looking for some maintainable solution. May be create a single table and store all this information in it.
Any suggestions are appreciated.
In SQL server you can query the system object :
information_schema.columns.
That contains a list of all columns for all tables and views.
However, I agree with previous comments - the design you describe is bad bad bad.
Ignoring the SQL injection troubles for a second, if the users have control over only the WHERE clause of the query, then you could try and run something like
select top 0 * from <tables> where <user-entered-where-clause>
and then gracefully handle any errors that are returned.
use dmv function in MS sql server to validate the query string.
assign user string to the variable #Str_query
declare #Str_query as nvarchar(max);
set #Str_query ='SELECT [role_code],[role_description] FROM [dbname].[dbo].[Roles]'
SELECT error_message FROM sys.dm_exec_describe_first_result_set(#Str_query, NULL, 0) WHERE column_ordinal = 0
if there is an error message then query string is not valid for execution.
Related
I'm attempting to create an Excel pivot table based on data in a Microsoft Dynamics NAV database.
The trick is I need the Excel to access the data directly from the SQL Server database with power query - and furthermore it must be able to access the data from the same table in multiple databases with different names and table names.
Does anybody have any experience or advice regarding this issue?
Step 1. First you should make a function where you can pass a server name, database name and table to be queried. Something like
let getData =(servername,dbname,tablename)=>
let
Source = Sql.Database(Servername, dbname, [Query="select abc , def from" & tablename & " where condition etc etc"]),
#"CustomStep1" = some action on Source,
in
.
.
#"CustomStepn" = some action on Added CustomStepn-1
in
#"Added CustomStepn"
in
getData
You have a function ready which you can use in a table to create a custom column.
Step 2. Now use a parameter table approach. Create a table in normal excel area.Something like
Server Name|DatabaseName | Table_to_be_used
Use now use menu option fromtable in powerquery options (or Data tab in Excel 16) Add a custom column in this table in powerquery steps using function getdata created in previous Step. Perform any other "Expand" (By default first function is going to return a table if you are not doing any other transformation) , "summarize" , Rename Operation.
However powerquery formula firewall is going to give you hardtime as powerquery doesn't trust Native SQL queries and you will have to approve each and every native sql query. You may try to uncheck checkbox for "Require user approval for new native database query" in query option.
Hope you get the idea and it helps.
Perhaps it would be worth looking into creating Query objects and exposing them via oData which is something Excel can read from. The benefit here is that it can handle table relations natively and can expose Flow Fields which you cannot see in direct SQL queries to the table.
Aside from a stored procedure to manage the different table names, there's not a simple way to query specific tables without hard coding the names in some capacity.
The Company table will give you the prefix$ and the table names are static between companies. You could write some fancy Excel logic to loop through them.
I have a web application that is written in MVC.Net using C# and LINQ-to-SQL (SQL Server 2008 R2).
I'd like to query the database for some values, and also insert those values into another table for later use. Obviously, I could do a normal select, then take those results and do a normal insert, but that will result in my application sending the values back to the SQL server, which is a waste as the server is where the values came from.
Is there any way I can get the select results in my application and insert them into another table without the information making a roundtrip from the the SQL server to my application and back again?
It would be cool if this was in one query, but that's less important than avoiding the roundtrip.
Assume whatever basic schema you like, I'll be extrapolating your simple example to a much more complex query.
Can I Insert the Results of a Select Statement Into Another Table Without a Roundtrip?
From a "single-query" and/or "avoid the round-trip" perspective: Yes.
From a "doing that purely in Linq to SQL" perspective: Well...mostly ;-).
The three pieces required are:
The INSERT...SELECT construct:
By using this we get half of the goal in that we have selected data and inserted it. And this is the only way to keep the data entirely at the database server and avoid the round-trip. Unfortunately, this construct is not supported by Linq-to-SQL (or Entity Framework): Insert/Select with Linq-To-SQL
The T-SQL OUTPUT clause:
This allows for doing what is essentially the tee command in Unix shell scripting: save and display the incoming rows at the same time. The OUTPUT clause just takes the set of inserted rows and sends it back to the caller, providing the other half of the goal. Unfortunately, this is also not supported by Linq-to-SQL (or Entity Framework). Now, this type of operation can also be achieved across multiple queries when not using OUTPUT, but there is really nothing gained since you then either need to a) create a temp table to dump the initial results into that will be used to insert into the table and then selected back to the caller, or b) have some way of knowing which rows that were just inserted into the table are new so that they can be properly selected back to the caller.
The DataContext.ExecuteQuery<TResult> (String, Object[]) method:
This is needed due to the two required T-SQL pieces not being supported directly in Linq-to-SQL. And even if the clunky approach to avoiding the OUTPUT clause is done (assuming it could be done in pure Linq/Lambda expressions), there is still no way around the INSERT...SELECT construct that would not be a round-trip.
Hence, multiple queries that are all pure Linq/Lambda expressions equates to a round-trip.
The only way to truly avoid the round-trip should be something like:
var _MyStuff = db.ExecuteQuery<Stuffs>(#"
INSERT INTO dbo.Table1 (Col1, Col2, Col2)
OUTPUT INSERTED.*
SELECT Col1, Col2, Col3
FROM dbo.Table2 t2
WHERE t2.Col4 = {0};",
_SomeID);
And just in case it helps anyone (since I already spent the time looking it up :), the equivalent command for Entity Framework is: Database.SqlQuery<TElement> (String, Object[])
try this query according your requirement
insert into IndentProcessDetails (DemandId,DemandMasterId,DemandQty) ( select DemandId,DemandMasterId,DemandQty from DemandDetails)
I have written a single stored procedure that returns 2 tables:
select *
from workers
select *
from orders
I call this stored procedure from my C# application and get a DataSet with two tables, and everything is working fine.
My question is how can I change the tables name at the SQL Server side so that in the C# side I will be able to access it via a name (instead of Tables[0]):
myDataSet.Tables["workers"]...
I tried to look for the answer in Google but couldn't find it. Maybe the search keywords was not sufficient.
You cannot really do anything from the server-side to influence those table names - those names only exist on the client-side, in your ADO.NET code.
What you can do is on the client-side - add table mappings - something like:
SqlDataAdapter dap = new SqlDataAdapter(YourSqlCommandHere);
dap.TableMappings.Add("Table", "workers");
dap.TableMappings.Add("Table1", "orders");
This would "rename" the Table (first result set) to workers and Table1 (second result set) to orders before you actually fill the data. So after the call to
dap.Fill(myDataSet);
you would then have myDataSet.Tables["workers"] and myDataSet.Tables["orders"] available for you to use.
The TDS Protocol documentation (Which is the protocol used to return results from SQL Server) does not mention a "resultset name". So the only way you will ever be able to access the result sets in ADO.net is by the number as mentioned in your example.
I have a current requirement to determine the table hierarchy from a sql statement within c#. For example, consider the following sql statement:
Select Table1.*, Table2.* from Table1
left join table2 on Table1.parentCol = Table2.childCol
That might return 7 columns, 3 for Table1 and 4 for table2. I need to know the column names, and ideally (though not mandatory) their types.
I have no control over what SQL Statement will be used, as this is a user entered field. In C# it's a very basic task to open a connection and create an SqlCommand using that statement. I have freedom to run the SQL into a SqlDataReader, or any other System.Data.SqlClient class if necessary, however I cannot find any combination that will return the columns, rather than the actual column values.
Is anyone able to help?
Many thanks and best regards
You cannot do what you are asking (easily).
More to the point, do not let users enter arbitrary TSQL (You will regret it at some point...).
Instead, create a 'Search' form that allows entering various params and use a parameterised query onto a view that joins all the tables/columns required.
There's no direct way. You'll need to parse names of all the tables from the sql query.
Once you have done that you'll need to write few queries on Information_Schema to get raw data for what you are looking for.
If you are on SQL Server, you may want to use Catalog View
ex-
Select * from sys.tables where [Name] = 'MyTable'
The point here is that I don't have the data base table names so please don't suggest to choose one table on to do on it 'SELECT COUNT(*)'
This depends on the database, but usually there are some tables that always exist or a table isn't even required.
For Oracle:
SELECT 1 FROM dual
For SqlServer:
SELECT 1
Not very elegant, but generally does the job if you know the database brand.
You haven't said what database type it is, but you could use something like DbConnection.GetSchema which is bound to need a working connection. I don't know how heavy a hit that would be though... if you knew more about the database type there may be a simpler "heartbeat" query you could perform.
You could run a command that doesn't query against a table, such as:
select ##VERSION