Is there a way to tell NHibernate to use square brackets for all table and column names (like [MyColumn]) when generating the SQL schema export for MS SQL Server? I have a legacy database that uses reserved names for certain columns and running the SQL script generated using NH throws an error because of it.
I want to avoid having to specify this separately for each column.
UPDATE: I'm using the correct dialect:
MsSqlConfiguration.MsSql2008.ConnectionString(connectionString)
UPDATE 2: #UpTheCreek pointed me in the right direction - backticks, which helped me find the answer in the "NHibernate in Action" book (p. 76):
There is no way, apart from quoting all table and column names in backticks, to force NHibernate to use quoted identifiers everywhere.
Easier approach:
SchemaMetadataUpdater.QuoteTableAndColumns(config)
(Before building SessionFactory)
That will quote all the reserved names automatically.
Use backticks in your mapping files around the column names. NH should replace these with the correct character for your db dialect (in your case square brackets).
i.e. use:
<class name="SomeClass" table="`SomeTable`">
NB - It won't work with an apostrophe. The backtick is located top left on most keyboards.
You need to use (or write) the correct dialect for your database
Related
I'm using DBeaver to write script for my PostgreSQL database.
I have a PostgreSQL DB with Tables autogenerated by C#/EFCore (Microsoft ORM) - I receive SQL Error [42P01] if I don't add double quotes around table names when I cut and paste my ORM queries to DBeaver. I got [42703] for fields without double quotes. I do not have to add double quotes in C# code but it appears to be required in DBeaver?
example:
select * from Dnp3PropertyBase => SQL Error [42P01]
select * from "Dnp3PropertyBase" => OK, all results shown...
Does anybody know if I can change a parameter in DBeaver somewhere in order to enter table names and fields without double quotes?
Note: Using DBeaver 22.3.2 (latest on 2023-01-11)
Update After reading: Postgresql tables exists, but getting "relation does not exist" when querying
show search_path => public, public, "$user"
SELECT * FROM information_schema.tables => All tables are in public schema
SELECT * FROM information_schema.columns => All columns are in public schema
Question: How to be able to cut and paste my EFCore generated queries from Visual Studio output window to DBeaver query without having any errors regarding table names and field names?
First let me copy #a_horse_with_no_name comment:
Unquoted names are folded to lower case in Postgres (and to uppercase
in Oracle, DB2, Firebird, and many others). So SomeTable is in fact
stored as sometable (or SOMETABLE). However quoted identifiers have to
preserve the case and are case sensitive then. So "SomeTable" is
stored as SomeTable
Many peoples recommended me to go with snake case which I didn't want to go with initialy because all tables were auto generated by EF Core (Microsoft C# ORM). I told myself that Microsoft would do standard things. Microsoft use the exact "class" name in code as the table name , by default. That appears to me very logical in order to stay coherent and apply the same rules everywhere. C# recommended to use Camel case for classes so each table names end by default in Camel case instead of snake case.
PostgreSQL seems to promote users to use snake casing because they lower case every non double quoted names. According to a_horse_with_no_name, and I think the same, only PostgreSQL has the behavior of lower casing down every table names and field names which are not double quoted in SQL script. That behavior (changing casing for non double quoted names) appears to me as being very limitative. It also has hidden effect that could be hard to find for non initiated peoples coming from other DB world.
According to PostgreSQL doc, they recommend to use nuget package (.UseSnakeCaseNamingConvention()). It probably works fine for TPH (table per hierarchy) which is recommended by Microsoft for performance. But it does not works for table name for TPC (table per class) because of actual bugs in EFCore 7 (see Github project).
I received that message at the end of "update-database":
Both 'WindTurbine' and 'ResourceGenerator' are mapped to the table
'resource_generator'. All the entity types in a non-TPH hierarchy (one
that doesn't have a discriminator) must be mapped to different tables.
See https://go.microsoft.com/fwlink/?linkid=2130430 for more
information.
PostgreSQL doc : TPH supported OK but not for table in TPC (2023-01-12). I use TPC then I had to force each table name directly through TableAttribute.
My solution For table name, I use snake casing by manually add a "Table" attribute to each of my classes with the proper name like this sample:
[Table("water_turbine")]
public class WaterTurbine : ResourceGenerator
For fields, I use the EFCore.NamingConventions NugetPackage which works fine for fields names. Don't forget that if you have 2 classes mapped to the same object, it is because you are using TPC and did not force table name through TableAttribute.
This way all my table and fields names are snake casing and I can cut and paste any query dumped in my debugger directly in any SQL script window of DBeaver (or any SQL tool).
I've got a strange problem. A customer named a field in FirebirdSQL start. Now I cannot select this field:
select t.start from table t
Gives me the error: Invalid token
Any idea on how I can select this field?
The word start is a reserved word in Firebird and therefor needs to be quoted. The quote symbol in Firebird is the double quote. So you need to use:
select t."start" from "table" t
Note that I quoted table as well, as it is also a reserved word. Quoting makes the name case sensitive, so you may need to use "START" and "TABLE".
In your comments you mention that quoting yields a constant value 'table'. This means that you are using dialect 1, the deprecated (and legacy) dialect of Firebird. This legacy dialect cannot quote object names, and the double quote is for string literals (next to the SQL standard single quotes). Either your database is a dialect 1 database, or you specified the wrong connection dialect in your connection library.
If you database is actually dialect 3, solving this is as simple as specifying connection dialect 3 (or 0 to auto select based on the database dialect). However if your database is a dialect 1 database you will need to migrate to dialect 3 to be able to solve this.
If this is simply to try things out: make sure you create a dialect 3 database (for most tools this is the default).
How to determine database dialect
To determine the database dialect, you can use the gstat tool:
gstat mydatabase.fdb -header
In recent Firebird versions you can also query the MON$DATABASE monitoring table. Most query tools also allow you to view the database properties.
How to migrate from dialect 1 to dialect 3
That is I think too complicated to write down here (and I have never done it myself as it was considered deprecated years ago). However the Interbase 6.0 Getting Started (available from Firebird: Reference Manuals (at the end of the page) describes the basic process of migration, and I am sure that there are pages to be found with some googling.
I have been using SQL Server CE for a while. In that database the table names were like
UserPosts, UserProfile.
But after my upgrade from SQL Server CE to SQL Server the names are edited to dbo.UserPosts, dbo.UserProfile. And also the names of columns are wrapped in square brackets like: [UserProfile].
Why is this bracket used?
Brackets are used to surround names in SQL Server (they server the same purpose as double quotes).
For names that consist of alphanumeric characters and underscore, do not start with a digit, and are not reserved words, the square brackets are not needed. They are typically used for columns that have "irregular" names, such as [Column Name] (note the space) or a reserved word like [from].
When SQL Server generates code, it is overly conservative (in my opinion) about the use of square brackets. It uses them for all column names, table names, and even type names in create table statements. Because I never use "irregular" characters in my names, I find all the brackets to be unnecessary clutter.
The dbo is something called a schema. SQL Server uses a three part naming convention for tables in a database: ... The database name defaults to the current data base, if it is not present. The schema defaults to dbo (or another default schema if that has been changed, which is almost never). And, there is a four part naming convention, where the first part is the server name.
I have SQL Server 2008 Express Edition installed and is my first time running a SQL query. I noticed that if I select to display the top 1000 rows that the query places brackets [] around the name of the database and its respective columns.
Why are there brackets around the name of the database and columns?
Is there a need to have these and if so when?
I just posted this answer on dba.stack.
They escape names that are not "friendly" - they can be useful if your database names contain special characters (such as spaces, dots or dashes) or represent SQL keywords (such as USE or DATABASE :-)). Without the square brackets, a query like this will fail:
SELECT column FROM database.dbo.table;
However if you write the query this way, the keywords are ignored:
SELECT [column] FROM [database].dbo.[table];
When building scripts or writing solutions that generate scripts from metadata (e.g. generating a script of all tables or all indexes), I always wrap entity names in square brackets so that they will work regardless of what kind of wonky names have been implemented (I am not always doing this for systems I control). You can do this easily using QUOTENAME function, e.g.:
SELECT QUOTENAME('table'), QUOTENAME('column'), QUOTENAME('database');
Results:
[table] [column] [database]
If you search my answers here for QUOTENAME you will find that I use it in a lot of scripts where I'm helping folks automate script generation or building dynamic SQL. Without the square brackets, a lot of people would run into issues running the scripts.
Enclosing a string in square braces is tells SQL Server that it should not try to parse whatever is inside them. This allows you to do use things like SQL reserved words (select, table, return, etc.) as well as spaces in identifiers. They are only required in those cases, but they are not harmful in any case.
No there isn't, but it ensures that if you had a db, table or column named as a reserved or keyword, for example date, that it wouldn't be confused with that keyword.
I have recently moved a database from Sql Server 2000 to Sql Server 2005. In the table designer, it insists on putting square brackets around a column named "Content" I don't see Content on the list of reserved words for Sql Server, so I don't understand why it is doing this. Is there a way I can prevent it?
CONTENT is a keyword when defining an XML column with a schema.
See here.
Edit: The MSDN link is broken (per Champ's comment), so here is the relevant extract:
Creating a typed XML column is as simple as adding the name of the schema inside parentheses, as you see here:
CREATE TABLE Foo(FooID INT, someXml XML(CONTENT FooSchema))
This statement indicates that the someXml column must adhere to the XML Schema Collection named FooSchema. You can specify that the XML must be a document or that it can contain a fragment by including the appropriate keyword, DOCUMENT or CONTENT, respectively. If omitted, the default is CONTENT.
The problem is that the field has the same name as the table. Sql Server 2000 did not seem to care about this potential ambiguity, but Sql Server 2005 does. When I add a field named Content to a table that is not named Content, the square brackets do not appear.
pamela
No, you can't prevent it. You can always add square brackets around a column name so it doesn't hurt anything.