MS Access + SQL Server front end concatenation problem (#NAME) - sql-server

When I link an SQL Server table to MS Access, I have an issue with concatenation of the SQL Server table/view columns.
I'm used to be doing this in Access: =[FirstName] & " " & [LastName]
However, when I do this with data linked from SQL Server, I get #NAME in the text field every time.
I tried to create a local dummy table in Access and the concatenation works without issues.
I also tried to type the concatenation in SQL Server format: =[FirstName] + ' ' + [LastName], without success.
My current workaround is to create all concatenations directly in the SQL View definitions, but this is quite limiting and I would like to be able to do concatenations directly in Access.
Is it possible?

This looks like a new bug in Access
I linked to a SQL table and added 2 text boxes to a form one an integer and one text
on the integer one =[field] & "b" works on the text field it fails.
even just =[textfieldname] throws an error
A workaround i found is to add firstname and lastname text boxes and rename them txtfirstname and txtlastname then add a third text box and give the datasource property = [txtfirstname] & " " & [txtlastname]
irritating as this used to work

Related

Parameterise a RecordSource query to ensure the data remains updateable?

I have a subform within a main form, that is set to datasheet view and extracts data from a SQL Server database, based on the forms supplied parameters.
This means that selecting a different team from the combobox or date from the datepicker, pulls the relevant information into the datasheet.
The user needs to be able to manipulate a boolean field within the data, and so far the only way I have found that I can make this data load and keep it updateable is to write the query in the .RecordSource property in VBA fully like below:
Set mf = mainFrm
S = " SELECT t.Date, t.Team, s.Username, t.Reference, t.Status, t.Reason, t.Completed " & _
" FROM [ODBC;DRIVER=SQL Server;SERVER=<SERVERNAME>;Integrated_Security=SSPI;DATABASE=<DBNAME>].testTbl as t " & _
" INNER JOIN [ODBC;DRIVER=SQL Server;SERVER=SRVFOSABESQL01;Integrated_Security=SSPI;DATABASE=MO_Productivity].staffTbl as s ON t.emp_id = s.emp_id " & _
" WHERE t.Team = '" & tmName & "' AND t.Date = #" & wkEnd & "# " & _
" ORDER BY t.Reference; "
mf.subFrm.Form.RecordSource = S
Obviously the huge issue here is that the provided variables are open to SQL injection, aren't going to be escaped and is obviously exposing the connection string. All of which can be worked around, but certainly doesn't feel 'best practice'.
I have tried using the .Recordset property to get data from the server with a pass-through parameterised query / stored procedure, but this seems to be a one-way read-only operation of placing the data in and making it 'unlinked' or not updateable.
What is the correct and more secure way to retrieve this data from SQL Server so it can be placed in the RecordSource to make it updateable?
I found this on fmsinc.com:
There are many reasons why a Query or Recordset may not be updateable. Some are pretty obvious:
The query is a Totals query (uses GROUP BY) or Crosstab query (uses
TRANSFORM), so the records aren't individual records
The field is a calculated field, so it can't be edited
You don't have permissions/rights to edit the table or database
The query uses VBA functions or user defined functions and the
database isn't enabled (trusted) to allow code to run
Some reasons are less obvious but can't be avoided:
The table being modified is a linked table without a primary key. For
certain backend databases (e.g. Microsoft SQL Server), Access/Jet
requires the table to be keyed to make any changes. This makes sense
since Access wants to issue a SQL query for modifications but can't
uniquely identify the record.
Less obvious are these situations:
List item
Queries with some summary fields linked to individual records and the
individual records still can't be edited
Queries with multi-table joins that are not on key fields
Union queries
If the query is updateable, then the recordset must be updateable. I solved this by using ADO object.
See MS Access 2019 - SQL Server 2017 - Recordset cannot be updated here on Stack Overflow.

SSIS - Dynamically loop over multiple databases

I have to consolidate data from from 1000+ databases having the same structure/tables in one unique DB.
DBs may be added and removed potentially on a daily basis so I need to retrieve the list of DBs dynamically and run the dynamically generated SQL query to extract data on each of them.
I designed the Data Flow with a query from a variable that is working fine if executed with a static value:
With a SQL task I get the list of instances, I loop over the them and with a nested Foreach Loop/SQL task I retrieve the database names and create the dynamic SQL with the following statement (DB name is anonymized):
SELECT 'select ''' + name + ''' as DatabaseName, ID from ' + name + '.[dbo].[Orders] as querytext FROM sys.databases WHERE name LIKE ( 'XXX%_%' );
This part is also working fine:
How can I use the result of the SQL task "Execute SQL Task - Get query text" as query to be executed in the Source "OLE DB Source 1" (part of "Data Flow Task 3")?
I tried mapping an Object variable "User::SqlCommandFromSQLTask" in the result set of the SQL task, then set it up as ADO object source variable and with a Script task convert it to string and pass the value to the variable SqlStringFromSQLTask3 (used as source in "OLE DB Source 1") but I get the error Violation of PRIMARY KEY constraint, like if the data flow is always running with a static value I set up as default:
While, if I remove the value from the variable panel, I get the error "Command text was not set for the command object.", even changing the property DelayValidation of the Data Flow to false.
Any help is much appreciated.
When I have used SSIS to connect to multiple SQL Server boxes, I have stored those SQL Server connection strings in a table in a central database. Then I use a query of that table as the input to the foreach loop data flow task. If we ever have to change a sql server connection string, which does happen, we just update that table with the newest value.

Using Dynamic Table name in ADO.NET Source Editor

I have an SSIS data flow task where I am trying to load data from a source table using ADO.NET Source Editor into a SQL Server table.
The problem:
The source table name is dynamic and depends on the current date.
Example: If I want to load today's data then the table name would be Sample_03292017_data and if loading tomorrow's data then it would be Sample_03302017_Data.
I did some research and found how to pass parameters to an ADO.NET Source Editor to use in where conditions but I couldn't find anything on how to use this parameter in a table name.
Does anyone know how I can achieve this? My query is really simple:
select * from Sample_[DateParameter]_Data.
I am using Visual Studio Data Tools 2010.
Expression must be set on the Data Flow Task not in the Ado.net Source
Follow this steps to set an expression for an Ado.net Source:
in the control flow tab click on the Data Flow Task and press F4 to show the properties tab
Click on the expression button, it show up a form like shown below
choose [Ado.net Source].sqlcommand property and click on the expression builder button
write the following expression "select * from Sample_ " + #[User::DateParameter] + "_Data" (assuming that your data parameter is stored in a variable named DateParameter)
You should use dynamic SQL to achieve this. If you are using ADO.net as Connection Type, copy and paste the following to your SQL statement:
Declare #SQL VARCHAR(MAX)
SET #SQL = 'Select * from ' + #TABLE
EXEC(#SQL)
In the parameter page, you need to Add new parameter which has #TABLE as the parameter name and leave the size as -1. The #Table variable should be decided by the expression from variable setting page.

Power Query Assign a string from excel to sql server variable

I am using Power query & I would like to assign a comma delimited string from an excel cell to a sql server variable. The power query I have so far is below. My Parameter is in a Excel "Table3" in "Column2" :
let
ProdParameterSource =Excel.CurrentWorkbook(){[Name="Table3"]}[Content]{0}[Column2],
Source = Sql.Database("server", "database", [Query="Declare #Product varchar(max) = "&(ProdParameterSource)&" select #Product"])
in
Source
I see the below error :
The parameters I am using as seen in the excel sheet are below :
How can I fix this error and see my input parameters in the sql server variable ABC as '44,216' (with the inverted comma).
I do not do a lot of power query but I do work in Power BI Desktop version.
First, you need to look at the reference to the SQL.Database() on MSDN.
It is looking for a whole query, either a dynamic string you make up or a call to a stored procedure.
My simple example below, pulls data from the Adventure Works DW 2012 Customer table.
What you are missing is a TSQL statement or multiple TSQL statements. Use the semicolon to combine statements into one batch to be called.
The example below create a variable #x as an integer and returns the value. This is almost like you example above.
You will be prompted for security (trusted credentials) and it will tell you that it is an unencrypted connection.
I did some looking around the NET. This article from Reeves Smith is like my last example but slanted towards power query and excel. Just remember, both products use the same engine.
https://reevessmith.wordpress.com/2014/08/19/power-query-and-stored-procedures-with-parameters/
Again
This will fix it: [Query="Declare #Product varchar(max) = '" & ProdParameterSource & "' select #Product"]).
This will fix it in a safer way, since you will escape any extra single-quotes which could break out of the string value: [Query="Declare #Product varchar(max) = '" & Text.Replace(ProdParameterSource, "'", "''") &"' select #Product"]).
What happened is that Power Query treats the text passed to Query as the entire script, and when you built the script you didn't put the value of ProdParameterSource in quotes, so the script appears to set a varchar value to 44,216 (without quotes). This is an invalid statement.

VBA empty string for insert into SQL Server

Here is the situation:
There's a SQL Server database with a Microsoft Access front end. There is a table in the SQL Server database with a column called PackID which is defined as VARCHAR(6) NOT NULL (it has to be NOT NULL because it's part of a composite primary key for this table). Empty strings are legitimate in the PackID column. In fact, they occur quite often. When the user enters data in the UI for this table, and tabs through the PackID field, an error message appears: "Cannot insert the value NULL into column 'PackID'; column does not allow nulls. INSERT fails."
Things that have been tried that do not work:
adding a default constraint on this column in the SQL Server database with a value of '' - apparently the default is only used if the column is omitted from the INSERT statement
setting the Default Value of the PackID field in Access to "" - it behaves as though "" is a NULL
calling the following VBA code when user moves off row in UI (Lost Focus event)
If IsNull(PackID.Value) Then
PackID.Value = ""
End If
Does anyone know how to force an empty string in Access so it's interpreted as an empty string for SQL Server and not a NULL?
Setting the Default Value in the text box Properties for PackID in Access to this
=" "
worked. The space between the double quotes is very important. Leaving the space out causes the insert to fail. In SQL Server LEN(PackID) returns 0. For instance:
SELECT LEN(''), LEN(' ');
both return 0. It appears as though SQL Server treats both of these as empty strings.
An alternative solution to this problem (no Default Value in text box Properties for PackID).
Private Sub Form_BeforeUpdate(Cancel As Integer)
If IsNull(PackID.Value) Or PackID.Value = "" Then
PackID.Value = " "
End If
End Sub
This still uses the concept of passing SQL Server " " (read this as quote space quote) as the field's value. On the UI side, this is an alternative to setting a default value for the field.

Resources