Configure postgresql.conf file through psql command - database

I want to write a script to configure postgresql.conf file, in which for every parameter it'll show the existing value and after that asked for updated value, then user will enter the updated value.
I'm unable to update the postgresql.conf files parameter through the update command while i can do the alter.
suppose i want to update "shared_preload_libraries" parameter in postgresql.conf which has already some values like
shared_preload_libraries='$libdir/dbms_pipe,$libdir/edb_gen,$libdir/dbms_aq '
Now i want to add 'pgaudit' like shared_preload_libraries='pgaudit,$libdir/dbms_pipe,$libdir/edb_gen,$libdir/dbms_aq '
i want to do the same through the command
I tried alter command only but it's not the way to update

Documentation:
In addition to postgresql.conf, a PostgreSQL data directory contains a file postgresql.auto.conf, which has the same format as postgresql.conf but is intended to be edited automatically, not manually. This file holds settings provided through the ALTER SYSTEM command. This file is read whenever postgresql.conf is, and its settings take effect in the same way. Settings in postgresql.auto.conf override those in postgresql.conf.
You can interact with the config via SQL commands SHOW and SET or functions current_setting() and set_config():
select set_config('shared_preload_libraries',
'pgaudit,'||current_setting('shared_preload_libraries'),
false);
Unfortunately, in case of shared_preload_libraries this will fail with ERROR: parameter "shared_preload_libraries" cannot be changed without restarting the server. This type of setting can only be changed directly or through ALTER SYSTEM SET..., in case of which the new value will be just saved to postgresql.auto.conf until you restart the server because it only applies at startup. If you want to load a library after startup, use LOAD.
ALTER SYSTEM can't be issued dynamically from functions and prepared statements or given a function:
ALTER SYSTEM
SET shared_preload_libraries = 'pgaudit'
|| current_setting('shared_preload_libraries');
--ERROR: syntax error at or near "||"
--LINE 3: || current_setting('shared_pr...
-- ^
prepare statement1 (text) as
alter system set shared_preload_libraries to $1;
execute statement1('pgaudit,'
||current_setting('shared_preload_libraries'));
--ERROR: syntax error at or near "alter"
--LINE 1: prepare statement1 (text) as alter system set shared_preload...
-- ^
do $$
declare current_setting text;
begin
select current_setting('shared_preload_libraries') into current_setting;
current_setting=rtrim(concat_ws(',','pgaudit','test',current_setting),',');
execute format ('alter system set shared_preload_libraries to %s',current_setting);
end $$;
--ERROR: ALTER SYSTEM cannot be executed from a function
--CONTEXT: SQL statement "alter system set shared_preload_libraries to pgaudit,test"
--PL/pgSQL function inline_code_block line 8 at EXECUTE

Related

EF Core idempotent migration script fails despite check on applied migration

I am using EF Core (3.1.15). In a previous migration (also created in 3.1.15), a column was referenced that was dropped later on. The idempotent script does check if the migration was performed on the database (which it is, and the reference still shows in the __EFMigrationsHistory table). However the check doesn't have the expected result and the script due to the inexistent column.
Q: why is the inexistent column tripping the execution of the SQL script?
Script was created with
dotnet-ef migrations script -i -o migrations.sql
Relevant part of the automated script that fails, where ReferenceToLedgerId is the column dropped in later migration:
IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger')
BEGIN
UPDATE LedgerTable SET LedgerId = ReferenceToLedgerId
END;
Error:
Msg 207, Level 16, State 1, Line 3
Invalid column name 'ReferenceToLedgerId'
When running the following SQL query, the result comes back as expected:
SELECT *
FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger'
MigrationId
ProductVersion
20210612052003_CLedger
3.1.15
The database is Azure SQL Database. Script doesn't fail on local SQL dev database. A dozen migrations have been applied since then, and only now the script fails.
Below was the call that created the specific script:
migrationBuilder.Sql("UPDATE LedgerTable set LedgerId = ReferenceToLedgerId", true);
I tried to place the table and column names in square brackets, but that made no difference (eg. [ReferenceToLedgerId]. The script fails in Azure DevOps release when using SQLCMD and also fails when using Azure Data Studio, both accessing the Azure SQL Database.
Additional check
I changed the script to do a quick check:
PRINT '#Before IF'
IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger')
BEGIN
PRINT '#Within IF'
--UPDATE LedgerTable SET LedgerId = ReferenceToLedgerId
END;
PRINT '#After IF'
To which I get the following result:
Started executing query at Line 1
#Before IF #After IF
Total execution time: 00:00:00.010
If I uncomment the UPDATE statement it fails again. So I can only conclude that the code path works as intended, but that the server still checks for the existence of the column. I am not familiar with SQL to understand why this would be, or why it only fails for this one line while the column itself is referenced in other lines of the SQL script without it failing.
That batch will fail on every version of SQL Server. eg
use tempdb
go
create table __EFMigrationsHistory(MigrationId nvarchar(200))
create table LedgerTable(LedgerId int)
go
insert into __EFMigrationsHistory(MigrationId) values (N'20210612052003_CLedger')
go
IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger')
BEGIN
UPDATE LedgerTable SET LedgerId = ReferenceToLedgerId
END;
Fails with
Msg 207, Level 16, State 1, Line 8
Invalid column name 'ReferenceToLedgerId'.
Because the batch cannot be parsed and compiled. It's simply not legal to reference a non-existent table or column in a TSQL batch.
You can work around this by using dynamic SQL, so that the batch referencing the non-existent column is not parsed and compiled unless the migration is being applied.
migrationBuilder.Sql("exec('UPDATE LedgerTable set LedgerId = ReferenceToLedgerId')", true);
This is documented here:
Tip
Use the EXEC function when a statement must be the first or only
one in a SQL batch. It might also be needed to work around parser
errors in idempotent migration scripts that can occur when referenced
columns don't currently exist on a table.
https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/operations

SQL Server : Create Procedure in DB without using [GO]

I want to execute this (simplified) query using node-mssql that executes in SQL Server 2017 fine:
USE [Journal]
[GO]
CREATE PROCEDURE [dbo].[EventDelete]
#NotificationID INT
AS
DELETE Notification
WHERE NotificationID = #NotificationID
[GO]
node-mssql declares syntax error using [GO] and requires semicolon, therefore I try this:
USE [Journal];
CREATE PROCEDURE [dbo].[EventDelete]
#NotificationID INT
AS
DELETE Notification
WHERE NotificationID = #NotificationID;
Now we get error:
CREATE/ALTER PROCEDURE' must be the first statement in a query batch.
So let's try this:
CREATE PROCEDURE [Journal].[dbo].[EventDelete]
#NotificationID INT
AS
DELETE Notification
WHERE NotificationID = #NotificationID;
Now we get
RequestError: 'CREATE/ALTER PROCEDURE' does not allow specifying the database name as a prefix to the object name.
Naturally without any DB declaration it attempts to attach to the master error:
CREATE PROCEDURE permission denied in database 'master'.
So writing the question really works at setting one's thoughts straight.
The reason is the stored procedure requires to be created in one batch, which [GO] signifies, with nothing else.
Execute USE [Journal] as one batch using the .batch('USE [Journal]') method and then the SQL to CREATE PROCEDUCE as a new .batch(...) execution, sequentially.
Unless there is another method within node-mssql which allows for multi-batch executions?

SSMS query - script won't run if database does not exist

I'm trying to do something like:
"If it exists, use it. If not, create it."
"If it exists, delete it. If not, create it."
One place it's definitely choking is the use it command - because if it DOES NOT EXIST - it chokes on the use command EVEN THOUGH that command will not run.
Here's more explanation:
I have a SQL Server script where I create a database and then I use the database.
The script will not run
because the use database command is invalid
because the database does not exist
but it will exist after the first command executes
but it doesn't matter because it doesn't exist NOW so the script will not run.
How do I put code in there that tries to use a database that might not exist?
How do I put code in there that will cause an error if run directly but WILL NOT RUN unless conditions are appropriate.
Please see the attached images.
Here's the code so you don't have to type it...
-- SQL SERVER: We can't run this script because CFPT does not exist.
-- ME: But it WILL exist after the first command runs
-- SQL SERVER: That does not matter - at THIS point in the code... it does not exist... tough luck
-- CREATE THE DATABASE
create database CFPT
-- USE THE DATABASE
USE CFPT
use master
drop database CFPT
Second code snippet:
-- SQL SERVER: We can't run this script because CFPT does not exist.
select db_id('CFPT') -- this just lets us see what the IF statement is going to have to deal with
IF db_id('CFPT') is null
begin
print 'DESIRED DB DOES NOT EXIST'
return
end
else
begin
use CFPT -- this line of code makes the whole script just not run.
end;
-- doesn't want to work - chokes on the use databasename (when the database does not exist)
(EDIT 1 start ////////////////////////////////////////////////////////////////////////////////////)
A third image was added with this edit - The SECOND image shows that the if/then/else statement will not work. The 3rd image shows that the database CFPT is not in the database list (left side of image) and the select statement was run (top highlighed code) and the results of that select (bottom red circle)
How do I get the if/then/else statement to work? (Because the THEN will not run if the conditions are not favorable shall-we-say)
(for some reason the red wavy lines are not showing up - they should be but they aren't - hmmm)
(EDIT 1 end ////////////////////////////////////////////////////////////////////////////////////)
(EDIT 2 start ////////////////////////////////////////////////////////////////////////////////////)
In relation to this question - trying to segregate commands that would normally fail but will not be attempted to be executed unless conditions are just right..... (see 4th image below) I'm segregating some commands with an IF statement (IF 1=2) but SQL Server is going into that IF statement even though the condition is false. Why is that?
(EDIT 2 end ////////////////////////////////////////////////////////////////////////////////////)
Try this ...
-- CREATE THE DATABASE
create database CFPT
GO
-- USE THE DATABASE
USE CFPT
use master
drop database CFPT
The GO command is a batch terminator, it separates the command to create the database from the command to use it.
See https://msdn.microsoft.com/en-us/library/ms188037.aspx
and
What is the use of GO in SQL Server Management Studio & Transact SQL?

variable value in file path in execute SQL Task in SSIS?

I am trying to use Execute SQL task in SSIS. but its not accepting variable value in path? The file name is dynamic so, it has to come from variable. The below code is direct input in Execute SQL task.
USE [master]
go
RESTORE DATABASE MyDb FROM
DISK = N'c:\DBRestores\?'
WITH REPLACE
go
then I used, Parameter Mapping to map that value but the task is failing.
Any help? Thanks
You can set dynamic parameter in the Expressions.
In Execute SQL Task Editor, goto Expressions -> Property -> SQLStatementSource -> Expression and put below SQL there, replace your dynamic variable name in it and click on Evaluate Expression and check the Evaluated Value.
"USE [master]
go
RESTORE DATABASE MyDb FROM
DISK = N'c:\\DBRestores\\" + #[User::VariableParameter] + "'
WITH REPLACE
go"
If the evaluated value is as expected, then the script would accept dynamic file names from variable.

ssis dynamically truncate table failed

I want to have a ssis package that would check the folder (and all of its subfolders) and import only files that match the predefined criteria. Depends on what the file name is, it will import into a certain database (all reside in the same sql server).
The process works like this:
1. check the matching files
2. for each matching file, parse the file's name to get information that determines where the file will be imported to
3. truncate the table that the file in the previous step will be loaded to
4. import the file (in Data Flow Task).
So far i got step 1 and 2 working, and the sql statement to truncate table populate as expected. I run this sql statement manually in ssms and it works.
But i can't pass step 3, got an error below:
Error: 0xC002F210 at Truncate table, Execute SQL Task: Executing the
query "set nocount on; truncate table [db1].[DBO].[TBL_B..." failed
with the following error: "Parameter name is unrecognized.". Possible
failure reasons: Problems with the query, "ResultSet" property not set
correctly, parameters not set correctly, or connection not established
correctly. Task failed: Truncate table
Attached are the setting of the package. What am i missing?
You can try to specify parameter by giving ParameterName as "0".
And since there will be no resultset to the truncate query, specify ResultSet as None.

Resources